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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;The following critieria can be applied to ascertain whether an EIP is mature (stable) enough to move to SFI:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It has been included in a devnet that has demonstrated stability (e.g., high participation, no critical bugs for ≥1 week).&lt;/li&gt;
  &lt;li&gt;The EIP specification is close to final (no placeholder values or pending design decisions).&lt;/li&gt;
  &lt;li&gt;It has minimal interactions with other CFI EIPs, OR those interactions have been tested in the same devnet.&lt;/li&gt;
  &lt;li&gt;Testing coverage is adequate (clients pass consensus tests, no known divergence across clients).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All Core Devs Testing (ACDT) calls may review EIPs to determine SFI eligibility. Status changes will then be ratified on ACDE or ACDC before assigning SFI status.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; signals that the EIP is on track for inclusion barring unforeseen issues. EIPs with incomplete specs or untested interactions should remain CFI until these conditions are met. The latest Upgrade Devnet must contain all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; Core EIPs.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;MAY&lt;/strong&gt; be moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; if circumstances necessitate removal, as agreed by client teams. An EIP &lt;strong&gt;MAY&lt;/strong&gt; also be moved from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt; if client teams remain in favor of including the EIP in the network upgrade but cannot commit to including it in the &lt;strong&gt;next&lt;/strong&gt; Upgrade Devnet.&lt;/p&gt;

&lt;p&gt;An EIP &lt;strong&gt;MUST&lt;/strong&gt; have a Python implementation accompanied by tests in &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/5cdb055e069e246a877c8aa018079eb0b9093f57/README.md&quot;&gt;execution-specs&lt;/a&gt;, submitted as an open PR or merged to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;devnets/upgradeName/version&lt;/code&gt; branch of the repository. Client developers &lt;strong&gt;MAY&lt;/strong&gt; decide to allow an EIP to be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt; without an &lt;a href=&quot;https://github.com/ethereum/execution-specs/blob/5cdb055e069e246a877c8aa018079eb0b9093f57/README.md&quot;&gt;execution-specs&lt;/a&gt; implementation, but the tests are strictly mandatory.&lt;/p&gt;

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

&lt;h3 id=&quot;included&quot;&gt;Included&lt;/h3&gt;

&lt;p&gt;After network upgrade activation, all included Core EIPs and activated non-Core EIPs &lt;strong&gt;MUST&lt;/strong&gt; be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; in the Meta EIP. All other status lists &lt;strong&gt;MUST&lt;/strong&gt; be removed from the Meta EIP.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; signals that the EIPs have been activated as part of the network upgrade.&lt;/p&gt;

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

&lt;p&gt;Formalizing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Proposed for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Considered for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Scheduled for Inclusion&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Declined for Inclusion&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Included&lt;/code&gt; stages provides better legibility to both protocol maintainers and the broader Ethereum community.&lt;/p&gt;

&lt;p&gt;The specification tries to minimize steps that &lt;strong&gt;MUST&lt;/strong&gt; be followed to align with Ethereum’s “rough consensus” governance model.&lt;/p&gt;

&lt;p&gt;Assuming it is adopted, the process outlined in this EIP should be used for at least one full network upgrade cycle before moving to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Last Call&lt;/code&gt; and at least two full network upgrade cycles before moving to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Final&lt;/code&gt;. This way, the EIP can be updated to reflect changes made to the process over time.&lt;/p&gt;

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

&lt;p&gt;This EIP does not directly change the Ethereum protocol. It formalizes parts of the current network upgrade planning process.&lt;/p&gt;

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

&lt;p&gt;None.&lt;/p&gt;

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

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

      </description>
        <pubDate>Wed, 12 Jun 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7723</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7723</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Code Index</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7744 - Code Index&lt;/strong&gt; is in Last Call status. It is authored by Tim Pechersky (@peersky) &lt;t@peersky.xyz&gt; and was originally created 2024-07-16. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-7744-code-index/20569&quot;&gt;https://ethereum-magicians.org/t/erc-7744-code-index/20569&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP defines a standard interface for indexing smart contracts on Ethereum by their bytecode hash. This enables trustless discovery and verification of contract code, facilitating use cases like bytecode signing, whitelisting, and decentralized distribution mechanisms.&lt;/p&gt;

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

&lt;p&gt;Existing contract discovery relies on addresses, which are non-deterministic and can be obfuscated through proxies. Indexing by bytecode hash provides a deterministic and tamper-proof way to identify and verify contract code, enhancing security and trust in the Ethereum ecosystem.&lt;/p&gt;

&lt;p&gt;Consider a security auditor who wants to attest to the integrity of a contract’s code. By referencing bytecode hashes, auditors can focus their audit on the bytecode itself, without needing to assess deployment parameters or storage contents. This method verifies the integrity of a contract’s codebase without auditing the entire contract state.&lt;/p&gt;

&lt;p&gt;Additionally, bytecode referencing allows whitelist contracts before deployment, allowing developers to get pre-approval for their codebase without disclosing the code itself, or even pre-setup infrastructure that will change it behavior upon adding some determined functionality on chain.&lt;/p&gt;

&lt;p&gt;For developers relying on extensive code reuse, bytecode referencing protects against malicious changes that can occur with address-based referencing through proxies. This builds long-term trust chains extending to end-user applications.&lt;/p&gt;

&lt;p&gt;For decentralized application (dApp) developers, a code index can save gas costs by allowing them to reference existing codebases instead of redeploying them, optimizing resource usage. This can be useful for dApps that rely on extensive re-use of same codebase as own dependencies.&lt;/p&gt;

&lt;h3 id=&quot;why-this-registry-needs-to-be-an-erc&quot;&gt;Why this registry needs to be an ERC&lt;/h3&gt;

&lt;p&gt;The Code Index is essential for trustless and secure smart contract development. By standardizing the interface for indexing contracts by their bytecode, developers can easily integrate this feature into their smart contracts, enhancing the security and trustworthiness of the Ethereum ecosystem.&lt;/p&gt;

&lt;p&gt;Its simplicity and generic nature make it suitable for a wide range of applications. The ability to globally reference the same codebase makes it an ideal candidate for standardization.&lt;/p&gt;

&lt;p&gt;Ultimately, this feature should be incorporated into EIP standards, as it is a fundamental building block for trustless and secure smart contract development. This standard is a step towards this goal.&lt;/p&gt;

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

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

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// SPDX-License-Identifier: CC0-1.0
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pragma&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;solidity&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IERC7744&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;./IERC7744.sol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @title Byte Code Indexer Contract
 * @notice You can use this contract to index contracts by their bytecode.
 * @dev This allows to query contracts by their bytecode instead of addresses.
 * @author Tim Pechersky (@Peersky)
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC7744&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC7744&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEIP7702&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes3&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;extcodecopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Copy first 3 bytes to memory
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Load the 3 bytes from memory
&lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prefix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xef0100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;codeHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;codeHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isEIP7702&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Registers a contract in the index by its bytecode hash
     * @param container The contract to register
     * @dev `msg.codeHash` will be used
     * @dev It will revert if the contract is already indexed or if returns EIP7702 delegated EOA
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invalid container&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isValidContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;etalon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alreadyExists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Indexed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;container&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codehash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Returns the contract address by its bytecode hash
     * @dev returns zero if the contract is not indexed
     * @param id The bytecode hash
     * @return The contract address
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;deployment-method&quot;&gt;Deployment method&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CodeIndex&lt;/code&gt; contract is deployed at: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC0De1D1126b6D698a0073A4e66520111cEe22F62&lt;/code&gt; using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CREATE2&lt;/code&gt; via the deterministic deployer at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x4e59b44847b379578588920ca78fbf26c0b4956c&lt;/code&gt; with a salt of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x9425035d50edcd7504fe5eeb5df841cc74fe6cccd82dca6ee75bcdf774bd88d9&lt;/code&gt; is obtained by seeking a vanity address starting with meaningful name “Code ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c0de1d&lt;/code&gt;) for a bytecode compiled with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solc 0.8.28&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;solc --input-file src/ERC7744.sol --bin --optimize --optimize-runs 2000 --metadata-hash none --via-ir --optimize-yul&lt;/code&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Bytecode over Addresses&lt;/strong&gt;: Bytecode is deterministic and can be verified on-chain, while addresses are opaque and mutable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reverting on re-indexing&lt;/strong&gt;: There is small, yet non-zero probability of hash collision attack. Disallowing updates to indexed location of bytecode coupes with this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple Interface&lt;/strong&gt;: The interface is minimal and focused to maximize composability and ease of implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Library Implementation&lt;/strong&gt;: Implementing this as a library would limit its impact, making code reuse more difficult and lacking a single, official source of truth. By establishing this as an ERC, we ensure standardization and widespread adoption, driving the ecosystem forward.&lt;/p&gt;

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

&lt;p&gt;Reference implementation of the Code Index can be found in the assets folder. There you can find the &lt;a href=&quot;/assets/eip-7744/IERC7744.sol&quot;&gt;interface&lt;/a&gt; and the &lt;a href=&quot;/assets/eip-7744/ERC7744.sol&quot;&gt;implementation&lt;/a&gt; of the Code Index.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Malicious Code&lt;/strong&gt;: The index does NOT guarantee the safety or functionality of indexed contracts. Users MUST exercise caution and perform their own due diligence before interacting with indexed contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storage contents of registered contracts&lt;/strong&gt;: The index only refers to the bytecode of the contract, not the storage contents. This means that the contract state is not indexed and may change over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt;&lt;/strong&gt;: The index does not index the EIP-7702 delegated accounts. During attempt to register, it checks if contract code begins with reserved delegation designator &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xef0100&lt;/code&gt; and if so, it will revert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-Destruct Contracts&lt;/strong&gt;: In case of indexed contract storage becomes empty, contracts may be re-indexed, During register function call, if contract is already indexed, we run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isValidContainer&lt;/code&gt; check on the indexed address. It it fails, re-indexing is allowed with a newly specified address.&lt;/p&gt;

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

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

      </description>
        <pubDate>Tue, 16 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7744</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7744</guid>
      </item>
      
    
      
    
      
      
      <item>
        <title>Composable Security Middleware Hooks</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7746 - Composable Security Middleware Hooks&lt;/strong&gt; is in Last Call status. It is authored by Tim Pechersky (@peersky) and was originally created 2024-07-17. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-7746-composable-security-middleware-hooks/19471&quot;&gt;https://ethereum-magicians.org/t/erc-7746-composable-security-middleware-hooks/19471&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This EIP proposes a standard interface, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt;, for implementing composable security layers in smart contracts. These layers act as middleware, enabling runtime validation of function calls before and after execution, independent of the protected contract’s logic. This approach facilitates modular security, allowing independent providers to manage and upgrade security layers across multiple contracts.&lt;/p&gt;

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

&lt;p&gt;Current smart contract security practices often rely on monolithic validation logic within the contract itself. This can lead to tightly coupled code, making it difficult to isolate and address security concerns. Better structured architecture is needed, middleware like approach is widely used in the industry, allowing to wrap calls in other calls in generic and repeatable pattern with same call signatures.&lt;/p&gt;

&lt;p&gt;The Security Layers Standard introduces a modular approach, enabling:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Independent Security Providers:&lt;/strong&gt; Specialized security providers can focus on developing and maintaining specific security checks.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Composable Security:&lt;/strong&gt; Layers can be combined to create comprehensive security profiles tailored to individual contract needs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Upgradability:&lt;/strong&gt; Security layers can be updated without requiring changes to the protected contract.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; Layers can perform a wide range of validation checks, including access control, input sanitization, output verification, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having a generalized standard for such layers can help to build more secure and modular systems as well as enable security providers to build generic, service-oriented security oracle solutions.&lt;/p&gt;

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

&lt;p&gt;A contract implementing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface MUST provide two functions:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ILayer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// @notice Validates a function call before execution.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param configuration Layer-specific configuration data.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param selector The function selector being called.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param sender The address initiating the call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param value The amount of ETH sent with the call (if any).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param data The calldata for the function call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return beforeCallResult Arbitrary data to be passed to `afterCallValidation`.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev MUST revert if validation fails.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beforeCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Validates a function call after execution.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param configuration Layer-specific configuration data.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param selector The function selector being called.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param sender The address initiating the call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param value The amount of ETH sent with the call (if any).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param data The calldata for the function call.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param beforeCallResult The data returned by `beforeCallValidation`.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev MUST revert if validation fails.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;afterCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;beforeCallResult&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

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

&lt;p&gt;A protected contract MAY integrate security layers by calling the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beforeCallValidation&lt;/code&gt; function before executing its logic and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;afterCallValidation&lt;/code&gt; function afterwards. Multiple layers can be registered and executed in a defined order. The protected contract MUST revert if any layer reverts.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Flexibility&lt;/strong&gt;: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;layerConfig&lt;/code&gt; parameter allows for layer-specific customization, enabling a single layer implementation to serve multiple contracts with varying requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;non-static calls&lt;/strong&gt;: Layers can maintain their own state, allowing for more complex validation logic (e.g., rate limiting, usage tracking).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strict Validation&lt;/strong&gt;: Reverts on validation failure ensure a fail-safe mechanism, preventing execution of potentially harmful transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gas Costs&lt;/strong&gt;: Layers naturally will have gas costs associated with their execution. However, the benefits of enhanced security and modularity outweigh these costs, especially as blockchain technology continues to evolve and we expect gas costs to decrease over time.&lt;/p&gt;

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

&lt;p&gt;A reference implementation of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface and a sample protected contract can be found in the repository:
In the &lt;a href=&quot;/assets/eip-7746/ILayer.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer.sol&lt;/code&gt;&lt;/a&gt; a reference interface is provided.&lt;/p&gt;

&lt;p&gt;In this test, a &lt;a href=&quot;/assets/eip-7746/test/Protected.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected.sol&lt;/code&gt;&lt;/a&gt; contract is protected by a &lt;a href=&quot;/assets/eip-7746/test/RateLimitLayer.sol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer.sol&lt;/code&gt;&lt;/a&gt; layer. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer&lt;/code&gt; implements the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ILayer&lt;/code&gt; interface and enforces a rate which client has configured.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; simulates a vulnerable contract that acts in a malicious way. In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;test.ts&lt;/code&gt; The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; contract is trying to drain the funds from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract. It is assumed that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract has bug that allows partial unauthorized access to the state.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateLimitLayer&lt;/code&gt; is configured to allow only 10 transactions per block from same sender. The test checks that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Drainer&lt;/code&gt; contract is not able to drain the funds from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protected&lt;/code&gt; contract.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Layer Trust&lt;/strong&gt;: Thoroughly audit and vet any security layer before integrating it into your contract. Malicious layers can compromise contract security.&lt;/p&gt;

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

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

      </description>
        <pubDate>Wed, 17 Jul 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7746</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7746</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Store, Table-Based Introspectable Storage</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7813 - Store, Table-Based Introspectable Storage&lt;/strong&gt; is in Last Call status. It is authored by alvarius (@alvrs), dk1a (@dk1a), frolic (@frolic), ludens (@ludns), vdrg (@vdrg), yonada &lt;yonada@proton.me&gt; and was originally created 2024-11-08. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-7813-store-table-based-introspectable-storage/21628&quot;&gt;https://ethereum-magicians.org/t/erc-7813-store-table-based-introspectable-storage/21628&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This standard 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.&lt;/p&gt;

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Using the storage mechanism defined in this ERC provides the following benefits:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Automatic Indexing&lt;/strong&gt;: By emitting consistent, standardized events during state changes, off-chain services can automatically track on-chain state and provide schema-aware indexer APIs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Elimination of Custom Getter Functions&lt;/strong&gt;: 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.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Simpler Upgradability&lt;/strong&gt;: This pattern leverages unstructured storage, making it easier to upgrade contract logic without the risks associated with using a fixed storage layout.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexible Data Extensions&lt;/strong&gt;: New tables can be added at runtime without without breaking existing integrations with other data consumers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reduced gas costs&lt;/strong&gt;: Using efficient data packing reduces gas costs for both storage and event emissions.&lt;/li&gt;
&lt;/ol&gt;

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

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

&lt;h4 id=&quot;store&quot;&gt;Store&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4 id=&quot;table&quot;&gt;Table&lt;/h4&gt;

&lt;p&gt;A storage structure that holds &lt;strong&gt;Records&lt;/strong&gt; sharing the same &lt;strong&gt;Schema&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;On-chain Table&lt;/strong&gt;: Stores its state on-chain and emits events for off-chain- indexers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Off-chain Table&lt;/strong&gt;: Does not store state on-chain but emits events for off-chain indexers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;record&quot;&gt;Record&lt;/h4&gt;

&lt;p&gt;A piece of data stored in a &lt;strong&gt;Table&lt;/strong&gt;, addressed by one or more keys.&lt;/p&gt;

&lt;h4 id=&quot;resourceid&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;A 32-byte value that uniquely identifies each &lt;strong&gt;Table&lt;/strong&gt; within the &lt;strong&gt;Store&lt;/strong&gt;.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Encoding:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Bytes (from left to right)&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Table type identifier&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2-31&lt;/td&gt;
      &lt;td&gt;Unique identifier&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Table Type Identifiers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7462&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;tb&quot;&lt;/code&gt;) for on-chain tables&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x6f74&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;ot&quot;&lt;/code&gt;) for off-chain tables&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;schema&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Used to represent the layout of Records within a table.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Schema&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each Table defines two schemas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key Schema: the types of the keys used to uniquely identify a &lt;strong&gt;Record&lt;/strong&gt; within a table. It consists only of fixed-length data types.&lt;/li&gt;
  &lt;li&gt;Value Schema: the types of the value fields of a &lt;strong&gt;Record&lt;/strong&gt; within a table, which can include both fixed-length and variable-length data types.&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Byte(s) from left to right&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Constraint&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Total byte length of static fields&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Number of static length fields&lt;/td&gt;
      &lt;td&gt;≤ (28 - number of dynamic length fields)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Number of dynamic length fields&lt;/td&gt;
      &lt;td&gt;For the key schema, 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;For the value schema, ≤5&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4-31&lt;/td&gt;
      &lt;td&gt;Each byte encodes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Dynamic-length types MUST come after all the static-length types.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;schematype&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Single byte that represents the type of a specific static or dynamic field.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SchemaType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;type-encoding&quot;&gt;Type Encoding&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Value Range&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x1F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; (increments of 8 bits)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x20&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x3F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int8&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256&lt;/code&gt; (increments of 8 bits)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x40&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x60&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x61&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x62&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x81&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x82&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xA1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int8[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xA2&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes1[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC2&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC4&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC5&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;fieldlayout&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Encodes the concrete value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;This encoding serves as an optimization for on-chain operations. By having the exact lengths readily available, the Store doesn’t need to repeatedly compute or translate the schema definitions into actual field lengths during execution.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FieldLayout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Byte(s) from left to right&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Constraint&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Total length of static fields&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Number of static length fields&lt;/td&gt;
      &lt;td&gt;≤ (28 - number of dynamic length fields)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Number of dynamic length fields&lt;/td&gt;
      &lt;td&gt;For the key schema, 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;For the value schema, ≤5&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4-31&lt;/td&gt;
      &lt;td&gt;Each byte encodes the byte length of the corresponding static field&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;encodedlengths&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Bytes (from least to most significant)&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0x00-0x06&lt;/td&gt;
      &lt;td&gt;uint56&lt;/td&gt;
      &lt;td&gt;Total byte length of dynamic data&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x07-0xB&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the first dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x0C-0x10&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the second dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x11-0x15&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the third dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x16-0x1A&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the fourth dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x1B-0x1F&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the fifth dynamic field&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;packed-data-encoding&quot;&gt;Packed Data Encoding&lt;/h3&gt;

&lt;p&gt;Record data returned by Store methods and included in Store events uses the following encoding rules.&lt;/p&gt;

&lt;h4 id=&quot;field-limits&quot;&gt;Field Limits&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Maximum Total Fields&lt;/strong&gt;: A record can contain up to &lt;strong&gt;28 fields&lt;/strong&gt; in total (both static and dynamic fields combined).
    &lt;ul&gt;
      &lt;li&gt;This limit is due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; type structure, which uses 28 bytes (bytes 4 to 31) to define field types, with one byte per field (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dynamic Fields Limit&lt;/strong&gt;: A record can have up to &lt;strong&gt;5 dynamic fields&lt;/strong&gt;.
    &lt;ul&gt;
      &lt;li&gt;This is due to the fact that a single 32 bytes word (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;) to encode the byte lengths of each dynamic field, instead of encoding each length separately as Solidity’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abi.encode&lt;/code&gt; would.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Static Fields Limit&lt;/strong&gt;: The maximum number of static fields is &lt;strong&gt;28 minus the number of dynamic fields&lt;/strong&gt;.
    &lt;ul&gt;
      &lt;li&gt;For example, if there are 5 dynamic fields, the maximum number of static fields is 23 (28 - 5).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;encoding-rules&quot;&gt;Encoding Rules&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;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’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abi.encodePacked&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;For dynamic-length fields (arrays, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;s):
    &lt;ul&gt;
      &lt;li&gt;If the field is an array, its elements are tightly packed without padding.&lt;/li&gt;
      &lt;li&gt;All dynamic fields are concatenated together without padding and without including their lengths.&lt;/li&gt;
      &lt;li&gt;The lengths of all dynamic fields are encoded into a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;example&quot;&gt;Example&lt;/h4&gt;

&lt;p&gt;Suppose a table has the following value schema:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Encoding (Pseudocode)&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This is a custom function as Solidity does not provide a way to tightly pack array elements
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packedScores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packElementsWithoutPadding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// abi.encodePacked concatenates both description and packedScores without including their lengths
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packedScores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Total length is encoded in the 56 least significant bits
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Each length is encoded using 5 bytes
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodedData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The full encoded record data is represented by the following tuple:
// (staticData, encodedLengths, dynamicData)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;All Stores MUST implement the following interface.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IStore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/**
   * Get full encoded record (all fields, static and dynamic data) for the given tableId and key tuple.
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/**
   * Get a single encoded field from the given tableId and key tuple.
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldIndex&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/**
   * Get the byte length of a single field from the given tableId and key tuple
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFieldLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldIndex&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The return values of both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt; use the encoding rules previously defined in the Packed Data Encoding section. More specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt; returns the fully encoded record tuple, and the data returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt; is encoded using the encoding rules as if the field was being encoded on its own.&lt;/p&gt;

&lt;h3 id=&quot;store-operations-and-events&quot;&gt;Store Operations and Events&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h4 id=&quot;store_setrecord&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event &lt;strong&gt;MUST&lt;/strong&gt; be emitted whenever the full data of a record has been overwritten.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SetRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the record is set&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;staticData&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The static data of the record using packed encoding&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;encodedLengths&lt;/td&gt;
      &lt;td&gt;EncodedLengths&lt;/td&gt;
      &lt;td&gt;The encoded lengths of the dynamic data of the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dynamicData&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The dynamic data of the record, using &lt;a href=&quot;#packed-data-encoding&quot;&gt;custom packed encoding&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_splicestaticdata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt; event MUST be emitted whenever the static data of the Record has been spliced.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SpliceStaticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint48&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the data is spliced&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;start&lt;/td&gt;
      &lt;td&gt;uint48&lt;/td&gt;
      &lt;td&gt;The start position in bytes for the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;data&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;Packed ABI encoding of a tuple with the value’s static fields&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_splicedynamicdata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt; event MUST be emitted whenever the dynamic data of the Record has been spliced.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SpliceDynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicFieldIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint48&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint40&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deleteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the data is spliced&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dynamicFieldIndex&lt;/td&gt;
      &lt;td&gt;uint8&lt;/td&gt;
      &lt;td&gt;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)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;start&lt;/td&gt;
      &lt;td&gt;uint48&lt;/td&gt;
      &lt;td&gt;The start position in bytes for the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;deleteCount&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;The number of bytes to delete in the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;encodedLengths&lt;/td&gt;
      &lt;td&gt;EncodedLengths&lt;/td&gt;
      &lt;td&gt;The resulting encoded lengths of the dynamic data of the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;data&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The data to insert into the dynamic data of the record at the start byte&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_deleterecord&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_DeleteRecord&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_DeleteRecord&lt;/code&gt; event MUST be emitted whenever the Record has been deleted from the Table.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_DeleteRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the record is deleted&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;See the &lt;a href=&quot;#reference-implementation&quot;&gt;reference implementation section&lt;/a&gt; for an example on how to index store events.&lt;/p&gt;

&lt;h3 id=&quot;the-tables-table&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table&lt;/h3&gt;

&lt;p&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table, which behaves the same way as other on-chain tables except for the special constraints mentioned below.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table MUST use the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;s:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key Schema:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tableId&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt; of the table this record describes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Value Schema:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fieldLayout&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt;): encodes the byte length of each static data type in the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keySchema&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;): represents the data types of the (composite) key of the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueSchema&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;): represents the data types of the value fields of the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abiEncodedKeyNames&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;): ABI encoded string array of key names.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abiEncodedFieldNames&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;): ABI encoded string array of field names.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Records stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table are considered immutable:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; MUST emit a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event for each table being registered.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; SHOULD NOT emit any other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; events for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Table&lt;/code&gt; registered in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table MUST store a record that describes itself before any other table is registered, emitting the corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event. The record must use the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tableId&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 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;) &amp;gt;&amp;gt; (2 * 8) | bytes32(&quot;Tables&quot;) &amp;gt;&amp;gt; (2 * 8 + 14 * 8)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x746273746f72650000000000000000005461626c657300000000000000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By using a predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; 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.&lt;/p&gt;

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

&lt;h3 id=&quot;splice-events&quot;&gt;Splice Events&lt;/h3&gt;

&lt;p&gt;While the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event suffices for tracking the data of each record off-chain, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Splice&lt;/code&gt; events (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt;) allows for more efficient partial updates. When only a portion of a record changes, emitting a full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetRecord&lt;/code&gt; event would be inefficient because the entire record data would need to be read from storage and emitted. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Splice&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3 id=&quot;disallowing-arrays-of-dynamic-types&quot;&gt;Disallowing Arrays of Dynamic Types&lt;/h3&gt;

&lt;p&gt;Arrays of dynamic types (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string[]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes[]&lt;/code&gt;) are intentionally not included as supported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ index: uint256, data: bytes }&lt;/code&gt;, where each array element is represented as an individual record.&lt;/p&gt;

&lt;h3 id=&quot;fieldlayout-optimization&quot;&gt;FieldLayout Optimization&lt;/h3&gt;

&lt;p&gt;Including the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; 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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table to decode the corresponding records.&lt;/p&gt;

&lt;h3 id=&quot;special-tables-table&quot;&gt;Special &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table&lt;/h3&gt;

&lt;p&gt;Including a special &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table provides significant benefits for off-chain indexers. While emitting events for table registration isn’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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;h3 id=&quot;store-event-indexing&quot;&gt;Store Event Indexing&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;We use TypeScript for this example but it can easily be replicated with other languages.&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`0x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create a key string from a table ID and key tuple to use in our store Map above&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Like `Array.splice`, but for strings of bytes&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;newData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataNibbles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newDataNibbles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`0x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataNibbles&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newDataNibbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;processStoreEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;StoreEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SetRecord&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Overwrite all of the Record&apos;s fields&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SpliceStaticData&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Splice the static field data of the Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;bytesLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SpliceDynamicData&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Splice the dynamic field data of the Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_DeleteRecord&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Delete the whole Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;h3 id=&quot;access-control&quot;&gt;Access Control&lt;/h3&gt;

&lt;p&gt;This standard only defines functions to &lt;strong&gt;read&lt;/strong&gt; from the Store (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getFieldLength&lt;/code&gt;). The methods for setting or modifying records in the store are left to each specific implementation. Therefore, implementations &lt;strong&gt;must provide appropriate access control mechanisms&lt;/strong&gt; for writing to the store, tailored to their specific use cases.&lt;/p&gt;

&lt;h3 id=&quot;on-chain-data-accessibility&quot;&gt;On-Chain Data Accessibility&lt;/h3&gt;

&lt;p&gt;All data stored within a store is accessible not only off-chain but also &lt;strong&gt;on-chain&lt;/strong&gt; by other smart contracts through the provided read functions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getFieldLength&lt;/code&gt;). 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.&lt;/p&gt;

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

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

      </description>
        <pubDate>Fri, 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>Confidential Transactions Supported Token</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #7945 - Confidential Transactions Supported Token&lt;/strong&gt; is in Last Call status. It is authored by Siyuan Zheng (@andrewcoder666) &lt;zhengsiyuan.zsy@antgroup.com&gt;, Zhe Han (@iampkuhz) &lt;hanzhe.hz@ant-intl.com&gt;, Xiaoyu Liu (@elizabethxiaoyu) &lt;jiushi.lxy@antgroup.com&gt;, Wenwei Ma (@madyinglight) &lt;huiwei.mww@antgroup.com&gt;, Jun Meng Tan (@chadxeth) &lt;junmeng.t@antgroup.com&gt;, Yuxiang Fu (@tmac4096) &lt;kunfu.fyx@antgroup.com&gt;, Kecheng Gao (@thanks-v-me-50) &lt;gaokecheng.gkc@antgroup.com&gt;, Alwin Ng Jun Wei (@alwinngjw) &lt;alwin.ng@antgroup.com&gt;, Chenxin Wang (@3235773541) &lt;wcx465603@antgroup.com&gt;, Xiang Gao (@GaoYiRu) &lt;gaoxiang.gao@antgroup.com&gt;, yuanshanhshan (@xunayuan) &lt;yuanshanshan.yss@antgroup.com&gt;, Hao Zou (@BruceZH0915) &lt;situ.zh@antgroup.com&gt;, Yanyi Liang &lt;eason.lyy@antgroup.com&gt;, Yuehua Zhang (@astroyhzcc) &lt;ruoying.zyh@antgroup.com&gt; and was originally created 2025-05-09. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/interface-of-confidential-transactions-supported-token-contract/23586&quot;&gt;https://ethereum-magicians.org/t/interface-of-confidential-transactions-supported-token-contract/23586&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;
&lt;p&gt;Classic token contracts like &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; enable their token holders to make transfers and/or approve others to make transfers on their behalves. The generality of token standard &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Confidential transactions have been implemented in many blockchains, either natively through blockchain protocols like Monero and Zcash, or through smart contracts like Zether&lt;sup id=&quot;fnref:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; without modifying the blockchain protocol.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Consequently, this proposal is to standardize confidential-transaction-supported token contracts, without loss of generality, by only specifying core methods and events.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Compared with application-specific confidential token designs, such as Confidential Fungible Token using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; 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.&lt;/p&gt;

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

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

&lt;h3 id=&quot;contract-interface&quot;&gt;Contract Interface&lt;/h3&gt;
&lt;p&gt;Compliant contracts MUST implement the following interface:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC7945&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialBalanceOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialBalance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialTransferFrom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialApprove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialAllowance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConfidentialTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConfidentialApproval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_currentAllowancePart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_allowancePart&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionally, compliant contracts MAY implement the following interface:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC7945Metadata&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;ierc7945metadata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7945Metadata&lt;/code&gt;&lt;/h4&gt;
&lt;h5 id=&quot;methods&quot;&gt;Methods&lt;/h5&gt;
&lt;h6 id=&quot;name&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;&lt;/h6&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returns the name of the token - e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;MyConfidentialToken&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.&lt;/p&gt;

&lt;h6 id=&quot;symbol&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol&lt;/code&gt;&lt;/h6&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returns the symbol of the token, e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;cHIX&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.&lt;/p&gt;

&lt;h6 id=&quot;decimals&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals&lt;/code&gt;&lt;/h6&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returns the number of decimals the token uses - e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt;, meaning the token amount should be divided by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;100000000&lt;/code&gt; to get its user representation.&lt;/p&gt;

&lt;p&gt;OPTIONAL - This method can be used to improve usability, but interfaces and other contracts MUST NOT expect this value to be present.&lt;/p&gt;

&lt;h4 id=&quot;ierc7945&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7945&lt;/code&gt;&lt;/h4&gt;
&lt;h5 id=&quot;methods-1&quot;&gt;Methods&lt;/h5&gt;

&lt;h6 id=&quot;confidentialbalanceof&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialBalanceOf&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialBalanceOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialBalance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returns the confidential balance of the account with address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;owner&lt;/code&gt;.&lt;/p&gt;

&lt;h6 id=&quot;confidentialtransfer&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransfer&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Transfers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; amount of tokens (behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt;) to address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_to&lt;/code&gt;, and MUST fire the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialTransfer&lt;/code&gt; event. The function SHOULD &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt; if the message caller’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; of this transfer fails to be verified.&lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implementations can fully customize the proof system, (de)serialization strategies of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, and/or the business workflow. For example, when implementing “Zether”&lt;sup id=&quot;fnref:1:1&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; confidential token contracts, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; and accounts’ confidential balances will be encrypted homomorphically under ElGamal public keys, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; will consist of 3 parts to check:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; is well encrypted under both the caller’s public key and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_to&lt;/code&gt;’s;&lt;/li&gt;
      &lt;li&gt;The plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; is non-negative;&lt;/li&gt;
      &lt;li&gt;The caller’s confidential balance is actually enough to pay the plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h6 id=&quot;confidentialtransferfrom&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransferFrom&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialTransferFrom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;

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

&lt;p&gt;Transfers &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; amount of tokens (behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt;) from address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_from&lt;/code&gt; to address &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_to&lt;/code&gt;, and MUST fire the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialTransfer&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransferFrom&lt;/code&gt; 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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt; unless the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_from&lt;/code&gt; account has deliberately authorized the sender of the message via some mechanism, and SHOULD &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt; if the message caller’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; of this transfer fails to be verified.&lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implementations can fully customize the proof system, (de)serialization strategies of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, and/or the business workflow. For example, when implementing “Zether” confidential token contracts, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; and accounts’ confidential balances will be encrypted homomorphically under ElGamal public keys, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; will consist of 3 parts to check:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; is well encrypted under public keys of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_from&lt;/code&gt;’s, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_to&lt;/code&gt;’s, and caller’s;&lt;/li&gt;
      &lt;li&gt;The plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt; is non-negative;&lt;/li&gt;
      &lt;li&gt;The caller’s confidential allowance is actually enough to pay the plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h6 id=&quot;confidentialapprove&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialApprove&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialApprove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_proof&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Allows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; to withdraw from caller’s split part of balances multiple times, up to the amount (allowance value) behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt; to 0. This function SHOULD &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt; if the message caller’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; of this transfer fails to be verified.&lt;/p&gt;

&lt;p&gt;Caution:&lt;/p&gt;

&lt;p&gt;This function behaves much &lt;strong&gt;differently from&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve(address,uint256)&lt;/code&gt; in &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialApprove&lt;/code&gt; splits the confidential balance of caller’s account into &lt;em&gt;allowance part&lt;/em&gt; and &lt;em&gt;the left part&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The values behind two parts above after calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialApprove&lt;/code&gt;, and the value behind the original confidential balance of caller’s account before calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialApprove&lt;/code&gt;, satisfy the equation:&lt;/p&gt;

\[value_{Behind\ Allowance\ Part} + value_{Behind\ Left\ Part} = value_{Behind\ Original\ Confidential\ Balance}\]

&lt;ul&gt;
  &lt;li&gt;The allowance part of the confidential balance allows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; to withdraw multiple times through calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransferFrom&lt;/code&gt; until &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; does not call it any more or the value behind this part is 0.
    &lt;ul&gt;
      &lt;li&gt;Every time &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransferFrom&lt;/code&gt;, the value behind this part will be decreased by the value behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialTransferValue&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The left part remains as the new confidential balance of the caller’s account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this function is called again, it:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;merges the existing allowance part into the confidential balance of the caller’s account; and then&lt;/li&gt;
  &lt;li&gt;overwrites the current allowance part with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Implementations can fully customize the proof system, (de)serialization strategies of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, and/or the business workflow. For example, when implementing “Zether” confidential token contracts, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt; and accounts’ confidential balances will be encrypted homomorphically under ElGamal public keys, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_proof&lt;/code&gt; will consist of 3 parts to check:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt; is well encrypted under public keys of caller’s and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt;’s;&lt;/li&gt;
      &lt;li&gt;The plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt; is non-negative;&lt;/li&gt;
      &lt;li&gt;The caller’s confidential balance is actually enough to pay the plaintext &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_confidentialValue&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h6 id=&quot;confidentialallowance&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialAllowance&lt;/code&gt;&lt;/h6&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialAllowance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Returns the allowance part that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; is still allowed to withdraw from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_owner&lt;/code&gt;.&lt;/p&gt;

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

&lt;h6 id=&quot;confidentialtransfer-1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialTransfer&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConfidentialTransfer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_confidentialTransferValue&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;MUST trigger when tokens are transferred.&lt;/p&gt;

&lt;p&gt;Specifically, if tokens are transferred through function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransferFrom&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_spender&lt;/code&gt; address MUST be set to caller’s; otherwise, it SHOULD be set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A confidential token contract:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;which creates new tokens SHOULD trigger a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialTransfer&lt;/code&gt; with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_from&lt;/code&gt; address set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0&lt;/code&gt; when tokens are minted;&lt;/li&gt;
  &lt;li&gt;which destroys existing tokens SHOULD trigger a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialTransfer&lt;/code&gt; with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_to&lt;/code&gt; address set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0&lt;/code&gt; when tokens are burned.&lt;/li&gt;
&lt;/ul&gt;

&lt;h6 id=&quot;confidentialapproval&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfidentialApproval&lt;/code&gt;&lt;/h6&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ConfidentialApproval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_spender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_currentAllowancePart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_allowancePart&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;MUST trigger on any successful call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialApprove(address,bytes,bytes)&lt;/code&gt;.&lt;/p&gt;

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

&lt;h3 id=&quot;optional-accessor-of-confidential-total-supply&quot;&gt;Optional Accessor of “Confidential Total Supply”&lt;/h3&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidentialTotalSupply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Confidentiality of transfer amount makes it hard to support a field like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalSupply()&lt;/code&gt; in &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;. When it comes to token minting or burning, if every user in this contract can access &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalSupply()&lt;/code&gt; as well as decrypt it, these users will know the actual token value minted or burned by comparing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalSupply()&lt;/code&gt; before and after such operations, which means that confidentiality no longer exists.&lt;/p&gt;

&lt;p&gt;Contract implementations can optionally support &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTotalSupply()&lt;/code&gt; 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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTotalSupply()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;anti-money-laundering-and-audit&quot;&gt;Anti-money Laundering and Audit&lt;/h3&gt;
&lt;p&gt;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 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransfer&lt;/code&gt; method signature, by encoding more information into parameters.&lt;/p&gt;

&lt;p&gt;For example, in a Zether-like implementation&lt;sup id=&quot;fnref:2&quot; role=&quot;doc-noteref&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot; rel=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;, if token transfers are required to be audited, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTransfer&lt;/code&gt; caller encrypts transfer &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; redundantly under public keys of caller’s, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt;’s, and a group of auditors’, which makes it possible for related parties to know the real &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; behind it exactly. So does &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;confidentialTotalSupply()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;fat-token&quot;&gt;Fat Token&lt;/h3&gt;
&lt;p&gt;A confidential-transactions-supported token can also implement &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; at the same time.&lt;/p&gt;

&lt;p&gt;Token accounts in such tokens can hold two kinds of balances. Such token contracts can optionally provide methods to hide &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; plaintext balances into confidential balances, and vice versa, to reveal confidential balances back to &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; plaintext balances.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; interfaces will bring much more usability and utility to confidential-transaction-supported tokens, realizing general confidentiality in the meantime.&lt;/p&gt;

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

&lt;p&gt;No backward compatibility issues found.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;
&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;footnotes&quot; role=&quot;doc-endnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot; role=&quot;doc-endnote&quot;&gt;

      &lt;pre&gt;&lt;code class=&quot;language-csl-json&quot;&gt;{
  &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;
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:1:1&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot; role=&quot;doc-endnote&quot;&gt;

      &lt;pre&gt;&lt;code class=&quot;language-csl-json&quot;&gt;{
  &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;
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;&lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot; role=&quot;doc-backlink&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

      </description>
        <pubDate>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>Facet-Based Diamonds</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8153 - Facet-Based Diamonds&lt;/strong&gt; is in Last Call status. It is authored by Nick Mudge (@mudgen) and was originally created 2026-02-07. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8153-facet-based-diamonds/27685&quot;&gt;https://ethereum-magicians.org/t/erc-8153-facet-based-diamonds/27685&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;A diamond is a proxy contract that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s to multiple implementation contracts called facets.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8153/basic-diamond-diagram.svg&quot; alt=&quot;Diagram showing how a diamond contract works&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diamond contracts were originally standardized by &lt;a href=&quot;/EIPS/eip-2535&quot;&gt;ERC-2535&lt;/a&gt;. This ERC builds on that foundation by defining a facet-based architecture in which facets self-describe their function selectors through a standardized introspection interface.&lt;/p&gt;

&lt;p&gt;By moving selector discovery on-chain, this approach eliminates the need for off-chain selector management. As a result, diamond deployment and upgrades become simpler, more deterministic, and more gas efficient.&lt;/p&gt;

&lt;p&gt;This ERC introduces a facet introspection function, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt;, which every facet MUST implement. This function returns the list of function selectors implemented by the facet, allowing a diamond to discover and register selectors on-chain during deployment or upgrade.&lt;/p&gt;

&lt;p&gt;This ERC also defines facet-based events for adding, replacing, and removing facets.&lt;/p&gt;

&lt;p&gt;Additionally, the ERC defines an optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function. This function uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; to automatically determine which selectors should be added, replaced, or removed when applying facet changes.&lt;/p&gt;

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

&lt;h3 id=&quot;motivation-for-diamond-contracts&quot;&gt;Motivation for Diamond Contracts&lt;/h3&gt;

&lt;p&gt;&lt;img alt=&quot;Obligatory diamond&quot; src=&quot;../assets/eip-8153/diamond.svg&quot; width=&quot;17%&quot; align=&quot;right&quot; /&gt;Through a single contract address, a diamond provides functionality from multiple implementation contracts (facets). Each facet is independent, yet facets can share internal functions and storage. This architecture allows large smart-contract systems to be composed from separate facets and presented as a single contract, simplifying deployment, testing, and integration with other contracts, off-chain software, and user interfaces.&lt;/p&gt;

&lt;p&gt;By decomposing large smart contracts into facets, diamonds can reduce complexity and make systems easier to reason about. Distinct areas of functionality can be isolated, organized, tested, and managed independently.&lt;/p&gt;

&lt;p&gt;Diamonds combine the single-address convenience of a monolithic contract with the modular flexibility of distinct, integrated contracts.&lt;/p&gt;

&lt;p&gt;This architecture is well suited to &lt;strong&gt;immutable&lt;/strong&gt; smart-contract systems, where all functionality is composed from multiple facets at deployment time and permanently fixed thereafter.&lt;/p&gt;

&lt;p&gt;For upgradeable systems, diamonds enable incremental development: new functionality can be added, and existing functionality modified, without redeploying unaffected facets.&lt;/p&gt;

&lt;p&gt;Additional motivation and background for diamond-based smart-contract systems can be found in &lt;a href=&quot;/EIPS/eip-1538&quot;&gt;ERC-1538&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-2535&quot;&gt;ERC-2535&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;motivation-for-this-standard&quot;&gt;Motivation for this Standard&lt;/h3&gt;

&lt;p&gt;In the past, deploying and upgrading diamonds suffered from:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;High gas costs&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function selector management complexity&lt;/strong&gt;
Deploying or upgrading a diamond requires assembling function selectors off-chain. Since common tooling (e.g., Hardhat, Foundry) does not natively manage diamond selectors, developers rely on custom scripts or third-party libraries to handle diamond “plumbing”.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This standard reduces gas costs and eliminates off-chain selector management:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Diamonds become less expensive to deploy.&lt;/li&gt;
  &lt;li&gt;Function selectors no longer need to be gathered off-chain.&lt;/li&gt;
  &lt;li&gt;Standard deployment tools can be used without special diamond support.&lt;/li&gt;
  &lt;li&gt;ERC-2535 introspection functions have simple implementations.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3 id=&quot;terms&quot;&gt;Terms&lt;/h3&gt;
&lt;ol&gt;
  &lt;li&gt;A &lt;strong&gt;diamond&lt;/strong&gt; is a smart contract that routes external function calls to one or more implementation contracts, referred to as facets. A diamond is stateful: all persistent data is stored in the diamond’s contract storage. A diamond implements the requirements in the &lt;a href=&quot;#implementation-requirements&quot;&gt;Implementation Requirements&lt;/a&gt; section.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;facet&lt;/strong&gt; is a smart contract that defines one or more external functions. A facet is deployed independently, and one or more of its functions are added to one or more diamonds. A facet’s functions are executed in the diamond’s context via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;, so reads/writes affect the diamond’s storage. The term facet is derived from the diamond industry, referring to a flat surface of a diamond.&lt;/li&gt;
  &lt;li&gt;An &lt;strong&gt;introspection function&lt;/strong&gt; is a function that returns information about the facets and/or functions used by a diamond or facet.&lt;/li&gt;
  &lt;li&gt;For the purposes of this specification, a &lt;strong&gt;mapping&lt;/strong&gt; refers to a conceptual association between two items and does not refer to a specific implementation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;diamond-diagram&quot;&gt;Diamond Diagram&lt;/h3&gt;

&lt;p&gt;This diagram shows the structure of a diamond.&lt;/p&gt;

&lt;p&gt;It shows that a diamond has a mapping from function to facet and that facets can access the storage inside a diamond.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/eip-8153/functionFacetMapping.svg&quot; alt=&quot;Diagram showing structure of a diamond&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;fallback&quot;&gt;Fallback&lt;/h3&gt;

&lt;p&gt;When an external function is called on a diamond, its fallback function is executed. The fallback function determines which facet to call based on the first four bytes of the calldata (known as the function selector) and executes the function from the facet using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A diamond’s fallback function and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; enable a diamond to execute a facet’s function as if it were implemented by the diamond itself. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.value&lt;/code&gt; values do not change and only the diamond’s storage is read and written to.&lt;/p&gt;

&lt;p&gt;Here is an example of how a diamond’s fallback function might be implemented:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionNotFound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Executes function call on facet using `delegatecall`.
// Returns function call return data or revert data.
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fallback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;payable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Get facet address from function selector
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selectorToFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionNotFound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Execute external function on facet using `delegatecall` and return any value.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Copy function selector and any arguments from calldata to memory.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;calldatacopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Execute function call using the facet.
&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;delegatecall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gas&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calldatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Copy all return data from the previous call into memory.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;returndatacopy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Return any return value or error back to the caller.
&lt;/span&gt;        &lt;span class=&quot;kr&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;revert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())}&lt;/span&gt;
        &lt;span class=&quot;kr&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;returndatasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h4 id=&quot;function-not-found&quot;&gt;Function Not Found&lt;/h4&gt;

&lt;p&gt;If the fallback function cannot find a facet for a function selector, and there is no default function or other mechanism to handle the call, the fallback MUST revert with the error &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionNotFound(bytes4 _selector)&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;inspecting-diamonds&quot;&gt;Inspecting Diamonds&lt;/h3&gt;

&lt;p&gt;A diamond implementing this standard MUST implement the same introspection functions as defined in ERC-2535.
Specifically, these functions MUST be implemented:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDiamondInspect&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Facet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;functionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets all facet addresses and their four byte function selectors.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facets_ Facet
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facets_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets all the function selectors supported by a specific facet.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param _facet The facet address.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetFunctionSelectors_
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetFunctionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetFunctionSelectors_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Get all the facet addresses used by a diamond.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetAddresses_
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddresses_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;/// @notice Gets the facet that supports the given selector.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @dev If facet is not found return address(0).
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @param _functionSelector The function selector.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;/// @return facetAddress_ The facet address.
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_functionSelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facetAddress_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Typically, these functions are implemented in a facet and the facet is added to diamonds.&lt;/p&gt;

&lt;h3 id=&quot;inspecting-facets&quot;&gt;Inspecting Facets&lt;/h3&gt;

&lt;p&gt;Each facet MUST implement the following pure introspection function:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IFacet&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exportSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array containing one or more 4-byte function selectors. The returned &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array length MUST be a multiple of 4, and each 4-byte chunk is a selector. The function MUST NOT return a specific selector more than once.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array contains selectors of functions implemented by the facet that are intended to be added to a diamond.&lt;/p&gt;

&lt;p&gt;This enables a diamond to discover selectors directly from facets at deployment or upgrade time. A diamond calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet to determine which selectors to add, replace, or remove.&lt;/p&gt;

&lt;p&gt;Selector gathering is therefore no longer an off-chain responsibility.&lt;/p&gt;

&lt;p&gt;This also means diamonds implementing this ERC are &lt;strong&gt;facet-based&lt;/strong&gt; rather than &lt;strong&gt;function-based&lt;/strong&gt;. Deployment and upgrades operate on facets.&lt;/p&gt;

&lt;h3 id=&quot;facet-based-events&quot;&gt;Facet-Based Events&lt;/h3&gt;

&lt;p&gt;This ERC replaces ERC-2535’s function-based events with facet-based events.&lt;/p&gt;

&lt;p&gt;When facets are added, replaced, or removed, the diamond MUST emit the following events:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;cm&quot;&gt;/**
  * @notice Emitted when a facet is added to a diamond.
  * @dev The function selectors this facet handles can be retrieved by calling
  *      `IFacet(_facet).exportSelectors()`
  *
  * @param _facet The address of the facet that handles function calls to the diamond.
  */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetAdded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Emitted when an existing facet is replaced with a new facet.
 * @dev
 * - Selectors that are present in the new facet but not in the old facet are added to the diamond.
 * - Selectors that are present in both the new and old facet are updated to use the new facet.
 * - Selectors that are not present in the new facet but are present in the old facet are removed from
 *   the diamond.
 *
 * The function selectors handled by these facets can be retrieved by calling:
 * - `IFacet(_oldFacet).exportSelectors()`
 * - `IFacet(_newFacet).exportSelectors()`
 *
 * @param _oldFacet The address of the facet that previously handled function calls to the diamond.
 * @param _newFacet The address of the facet that now handles function calls to the diamond.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetReplaced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_newFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Emitted when a facet is removed from a diamond.
 * @dev The function selectors this facet handles can be retrieved by calling
 *      `IFacet(_facet).exportSelectors()`
 *
 * @param _facet The address of the facet that previously handled function calls to the diamond.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetRemoved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Block explorers and other tooling can obtain the function selectors for any of the facets referenced by these events by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet address.&lt;/p&gt;

&lt;h3 id=&quot;optional-events&quot;&gt;Optional Events&lt;/h3&gt;

&lt;h4 id=&quot;recording-non-fallback-delegatecalls&quot;&gt;Recording Non-Fallback &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s&lt;/h4&gt;

&lt;p&gt;This event is OPTIONAL, except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; functions MUST emit it as specified in this standard.&lt;/p&gt;

&lt;p&gt;This event can be used to record &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by a diamond.&lt;/p&gt;

&lt;p&gt;This event MUST NOT be emitted for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by a diamond’s fallback function when routing calls to facets. It is only intended for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;s made by functions in facets or a diamond’s constructor.&lt;/p&gt;

&lt;p&gt;This event enables tracking of changes to a diamond’s contract storage caused by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; execution.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
* @notice Emitted when a diamond&apos;s constructor or function from a
*         facet makes a `delegatecall`. 
* 
* @param _delegate         The contract that was the target of the `delegatecall`.
* @param _delegateCalldata The function call, including function selector and 
*                          any arguments.
*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DiamondDelegateCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;diamond-metadata&quot;&gt;Diamond Metadata&lt;/h4&gt;

&lt;p&gt;This event is OPTIONAL, except &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; functions MUST emit it as specified in this standard.&lt;/p&gt;

&lt;p&gt;This event can be used to record versioning or other information about diamonds.&lt;/p&gt;

&lt;p&gt;It can be used to record information about diamond upgrades.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
* @notice Emitted to record information about a diamond.
* @dev    This event records any arbitrary metadata. 
*         The format of `_tag` and `_data` are not specified by the 
*         standard.
*
* @param _tag   Arbitrary metadata, such as a release version.
* @param _data  Arbitrary metadata.
*/&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DiamondMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;implementation-requirements&quot;&gt;Implementation Requirements&lt;/h3&gt;

&lt;p&gt;A facet-based diamond MUST implement the following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Diamond Structure&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fallback()&lt;/code&gt; function.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function Association&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;It MUST associate function selectors with facet addresses.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Function Execution&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;When an external function is called on a diamond:
        &lt;ul&gt;
          &lt;li&gt;The diamond’s fallback function is executed.&lt;/li&gt;
          &lt;li&gt;The fallback function MUST find the facet associated with the function selector.&lt;/li&gt;
          &lt;li&gt;The fallback function MUST execute the function on the facet using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;If no facet is associated with the function selector, the diamond MAY execute a default function or apply another handling mechanism.&lt;/li&gt;
          &lt;li&gt;If no facet, default function, or other handling mechanism exists, execution MUST revert with the error &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FunctionNotFound(bytes4 _selector)&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Events&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;The following events MUST be emitted:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetAdded&lt;/code&gt; — when a facet is added to a diamond.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetReplaced&lt;/code&gt; — when a facet is replaced with a different facet.&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetRemoved&lt;/code&gt; — when a facet is removed from a diamond.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Diamond Introspection&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;A diamond MUST implement the following introspection functions:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facets()&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetFunctionSelectors(address _facet)&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetAddresses()&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;facetAddress(bytes4 _functionSelector)&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Facet Introspection&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Each facet MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; function, which returns a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; array.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;receive-function&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive()&lt;/code&gt; Function&lt;/h3&gt;

&lt;p&gt;A diamond MAY have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receive()&lt;/code&gt; function.&lt;/p&gt;

&lt;h3 id=&quot;upgradediamond-function&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; Function&lt;/h3&gt;

&lt;p&gt;Implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; is OPTIONAL.&lt;/p&gt;

&lt;p&gt;This function is specified for interoperability with tooling (e.g., GUIs and command-line tools) so that upgrades can be executed with consistent and predictable behavior.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; adds, replaces, and removes any number of facets in a single transaction. It can also optionally execute a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; to perform initialization or state migration.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function works as follows:&lt;/p&gt;

&lt;h4 id=&quot;adding-a-facet&quot;&gt;Adding a Facet&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Add each selector to the diamond, mapping it to the facet address.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;replacing-a-facet&quot;&gt;Replacing a Facet&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the old facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the new facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;For selectors present in the new facet but not the old facet: add them.&lt;/li&gt;
  &lt;li&gt;For selectors present in both: replace them to point to the new facet.&lt;/li&gt;
  &lt;li&gt;For selectors present in the old facet but not the new facet: remove them.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;removing-a-facet&quot;&gt;Removing a Facet&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on the facet to obtain its function selectors.&lt;/li&gt;
  &lt;li&gt;Remove each selector from the diamond.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;errors-and-types&quot;&gt;Errors and Types&lt;/h4&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @notice The upgradeDiamond function below detects and reverts
 *         with the following errors.
 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NoSelectorsForFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NoBytecodeAtAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_contractAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotAddFunctionToDiamondThatAlreadyExists&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotRemoveFacetThatDoesNotExist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotReplaceFacetWithSameFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetToReplaceDoesNotExist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DelegateCallReverted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ExportSelectorsCallFailed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_facet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @dev This error means that a function to replace exists in a
 *      facet other than the facet that was given to be replaced.
 */&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CannotReplaceFunctionFromNonReplacementFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @notice This struct is used to replace old facets with new facets.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FacetReplacement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFacet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;function-signature&quot;&gt;Function Signature&lt;/h4&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
 * @notice Upgrade the diamond by adding, replacing, or removing facets.
 *
 * @dev
 * Facets are added first, then replaced, then removed.
 *
 * These events are emitted to record changes to facets:
 * - `FacetAdded(address indexed _facet)`
 * - `FacetReplaced(address indexed _oldFacet, address indexed _newFacet)`
 * - `FacetRemoved(address indexed _facet)`
 *
 * If `_delegate` is non-zero, the diamond performs a `delegatecall` to
 * `_delegate` using `_delegateCalldata`. The `DiamondDelegateCall` event is
 *  emitted.
 *
 * The `delegatecall` is done to alter a diamond&apos;s state or to
 * initialize, modify, or remove state after an upgrade.
 *
 * However, if `_delegate` is zero, no `delegatecall` is made and no
 * `DiamondDelegateCall` event is emitted.
 *
 * If _tag is non-zero or if _metadata.length &amp;gt; 0 then the
 * `DiamondMetadata` event is emitted.
 *
 * @param _addFacets        Facets to add.
 * @param _replaceFacets    (oldFacet, newFacet) pairs, to replace old with new.
 * @param _removeFacets     Facets to remove.
 * @param _delegate         Optional contract to delegatecall (zero address to skip).
 * @param _delegateCalldata Optional calldata to execute on `_delegate`.
 * @param _tag              Optional arbitrary metadata, such as release version.
 * @param _metadata         Optional arbitrary data.
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upgradeDiamond&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_addFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FacetReplacement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_replaceFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_removeFacets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_delegateCalldata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_tag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_metadata&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function MUST adhere to the following requirements:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Definitions of events and custom errors referenced below are given earlier in this standard.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Inputs&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_addFacets&lt;/code&gt; array of facet addresses to add.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_replaceFacets&lt;/code&gt; array of (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldFacet&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newFacet&lt;/code&gt;) pairs.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_removeFacets&lt;/code&gt; array of facet addresses to remove.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Execution Order&lt;/strong&gt;
    &lt;ol&gt;
      &lt;li&gt;Add facets&lt;/li&gt;
      &lt;li&gt;Replace facets&lt;/li&gt;
      &lt;li&gt;Remove facets&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Event Emission&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Every change to a facet MUST emit exactly one of:
        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetAdded&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetReplaced&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetRemoved&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Error Conditions&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;The implementation MUST detect and revert with the specified error when:
        &lt;ul&gt;
          &lt;li&gt;Adding a selector that already exists: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotAddFunctionToDiamondThatAlreadyExists&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Removing a facet that does not exist: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotRemoveFacetThatDoesNotExist&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a facet with itself: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotReplaceFacetWithSameFacet&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a facet that does not exist: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FacetToReplaceDoesNotExist&lt;/code&gt;.&lt;/li&gt;
          &lt;li&gt;Replacing a selector that exists in the diamond but is mapped to a facet different than the facet being replaced: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CannotReplaceFunctionFromNonReplacementFacet&lt;/code&gt;.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Facet Validation&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If any facet address contains no contract bytecode, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoBytecodeAtAddress&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; is missing, reverts, or cannot be called successfully, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ExportSelectorsCallFailed&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns zero selectors, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoSelectorsForFacet&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Delegate Validation&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; is non-zero but contains no bytecode, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NoBytecodeAtAddress&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Delegatecall Execution&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; is non-zero, the diamond MUST &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegate&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegateCalldata&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; fails and returns revert data, the diamond MUST revert with the same revert data.&lt;/li&gt;
      &lt;li&gt;If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; fails and returns no revert data, revert with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DelegateCallReverted&lt;/code&gt;.&lt;/li&gt;
      &lt;li&gt;If a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; is performed, the diamond MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DiamondDelegateCall&lt;/code&gt; event.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_delegateCalldata&lt;/code&gt; MAY be empty. If empty, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; executes with no calldata.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Metadata Event&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_tag&lt;/code&gt; is non-zero or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_metadata.length &amp;gt; 0&lt;/code&gt;, the diamond MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DiamondMetadata&lt;/code&gt; event.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After adding, replacing, or removing facets, the diamond MAY perform a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; to initialize, migrate, or clean up state.&lt;/p&gt;

&lt;p&gt;It is also valid to call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; solely to perform a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; (i.e., without adding, replacing, or removing any facets).&lt;/p&gt;

&lt;p&gt;To skip an operation, supply an empty array for its parameter (for example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new address[](0)&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_addFacets&lt;/code&gt;).&lt;/p&gt;

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

&lt;h3 id=&quot;eliminating-selector-management&quot;&gt;Eliminating Selector Management&lt;/h3&gt;

&lt;p&gt;To deploy a facet-based diamond implementing this ERC, the deployer provides an array of facet addresses to the diamond constructor. The constructor calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet and registers those selectors in the diamond.&lt;/p&gt;

&lt;p&gt;Because facets self-describe their selectors, deployers no longer need to gather selectors off-chain or depend on specialized selector tooling.&lt;/p&gt;

&lt;h3 id=&quot;reducing-deployment-gas-costs&quot;&gt;Reducing Deployment Gas Costs&lt;/h3&gt;

&lt;h4 id=&quot;reducing-calldata&quot;&gt;Reducing Calldata&lt;/h4&gt;

&lt;p&gt;In a non-facet-based diamond, selectors are typically passed to the constructor as one or more &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; arrays. These arrays are paid for in calldata and then copied into memory, incurring additional gas.&lt;/p&gt;

&lt;p&gt;In a facet-based diamond, only facet addresses are passed to constructors. The diamond calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; on each facet to obtain selectors on-chain, avoiding calldata costs for selector lists. While calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; introduces some overhead, non-facet-based diamonds typically perform code-existence checks (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extcodesize&lt;/code&gt;) on facet addresses anyway, incurring the cold account access gas cost.&lt;/p&gt;

&lt;h4 id=&quot;reducing-storage&quot;&gt;Reducing Storage&lt;/h4&gt;

&lt;p&gt;In a &lt;strong&gt;non-facet-based diamond&lt;/strong&gt;, function selectors are stored directly for introspection, typically in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[] selectors&lt;/code&gt; array (or an equivalent structure). Because a storage slot is 32 bytes, each slot can hold up to eight &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4&lt;/code&gt; selectors. As more functions are added, additional storage slots are required, so storage usage grows linearly with the number of selectors.&lt;/p&gt;

&lt;p&gt;In a &lt;strong&gt;facet-based diamond&lt;/strong&gt;, introspection data can be stored &lt;strong&gt;per facet instead of per function&lt;/strong&gt;. Each facet only needs a single representative selector. This means one 32-byte storage slot can represent up to eight facets, regardless of how many function selectors each facet implements. Storage usage therefore grows with the number of facets, not the number of functions.&lt;/p&gt;

&lt;p&gt;Alternatively, a facet-based diamond can be implemented as a &lt;strong&gt;linked list of facets&lt;/strong&gt;. With this design, introspection requires a &lt;strong&gt;single 32-byte storage slot&lt;/strong&gt;, while supporting any number of facets and any number of selectors per facet.&lt;/p&gt;

&lt;h3 id=&quot;exportselectors-function-return-value&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; Function Return Value&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; for two reasons:&lt;/p&gt;

&lt;h4 id=&quot;bytes4-wastes-memory&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; Wastes Memory&lt;/h4&gt;

&lt;p&gt;Each element of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4[]&lt;/code&gt; array occupies 32 bytes in memory, but only 4 bytes are meaningful. This wastes 87.5% of allocated memory, increasing gas costs. Packing selectors into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt; reduces memory overhead.&lt;/p&gt;

&lt;h4 id=&quot;simple-syntax-for-facets&quot;&gt;Simple Syntax For Facets&lt;/h4&gt;

&lt;p&gt;Facets can implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; concisely using Solidity’s built-in function &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes.concat&lt;/code&gt;. Example:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exportSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetFunctionSelectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facetAddresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;facets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The diamond can traverse the returned bytes and extract selectors efficiently.&lt;/p&gt;

&lt;h3 id=&quot;diamond-upgrades&quot;&gt;Diamond Upgrades&lt;/h3&gt;

&lt;p&gt;The upgrade function specified by this standard is optional.&lt;/p&gt;

&lt;p&gt;This means a couple of things:&lt;/p&gt;

&lt;h4 id=&quot;1-diamonds-can-be-immutable&quot;&gt;1. Diamonds Can Be Immutable&lt;/h4&gt;

&lt;p&gt;A Diamond does not have to have an upgrade function.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;A diamond can be fully constructed within its constructor without adding any upgrade function, making it immutable upon deployment.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A large immutable diamond can be built using well organized facets.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;A diamond can initially be upgradeable, and later made immutable by removing its upgrade function.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-you-can-create-your-own-upgrade-functions&quot;&gt;2. You Can Create Your Own Upgrade Functions&lt;/h4&gt;

&lt;p&gt;You can design and create your own upgrade functions and remain compliant with this standard. All that is required is that you emit the appropriate add/replace/remove events specified in the &lt;a href=&quot;#facet-based-events&quot;&gt;Facet-Based Events section&lt;/a&gt;, and that the introspection functions defined in the &lt;a href=&quot;#inspecting-diamonds&quot;&gt;Inspecting Diamonds section&lt;/a&gt; and the &lt;a href=&quot;#inspecting-facets&quot;&gt;Inspecting Facets section&lt;/a&gt; continue to exist and accurately return function and facet information.&lt;/p&gt;

&lt;h3 id=&quot;runtime-gas-considerations&quot;&gt;Runtime Gas Considerations&lt;/h3&gt;

&lt;p&gt;Routing calls via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; introduces a small amount of gas overhead. In practice, this cost is mitigated by several architectural and tooling advantages enabled by diamonds:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Optional, gas-optimized functionality&lt;/strong&gt;&lt;br /&gt;
By structuring functionality across multiple facets, diamonds make it straightforward to include specialized, gas-optimized features without increasing the complexity of core logic.&lt;br /&gt;
For example, an &lt;a href=&quot;/EIPS/eip-721&quot;&gt;ERC-721&lt;/a&gt; diamond may implement batch transfer functions in a dedicated facet, improving both gas efficiency and usability while keeping the base ERC-721 implementation simple and well-scoped.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Reduced external call overhead&lt;/strong&gt;  &lt;br /&gt;
Some contract architectures require multiple external calls within a single transaction. By consolidating related functionality behind a single diamond address, these interactions can execute internally with shared storage and shared authorization, reducing gas costs from external calls and repeated access-control checks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Selective optimization per facet&lt;/strong&gt;&lt;br /&gt;
Because facets are compiled and deployed independently, they may be built with different compiler optimizer settings. This allows gas-critical facets to use aggressive optimization configurations to reduce execution costs, without increasing bytecode size or compilation complexity for unrelated functionality.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;storage-layout&quot;&gt;Storage Layout&lt;/h3&gt;

&lt;p&gt;Diamonds and facets need to use a storage layout organizational pattern because Solidity’s default storage layout doesn’t support proxy contracts or diamonds. The storage layout technique or pattern to use is not specified in this ERC. However, examples of storage layout patterns that work with diamonds are &lt;a href=&quot;/EIPS/eip-8042&quot;&gt;ERC-8042 Diamond Storage&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-7201&quot;&gt;ERC-7201 Namespaced Storage Layout&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;facets-sharing-storage--functionality&quot;&gt;Facets Sharing Storage &amp;amp; Functionality&lt;/h3&gt;

&lt;p&gt;Facets are separately deployed, independent units, but can share state and functionality in the following ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Facets can share state variables by using the same structs at the same storage positions.&lt;/li&gt;
  &lt;li&gt;Facets can share internal functions by importing them or inheriting contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;on-chain-facets-can-be-reused-and-composed&quot;&gt;On-chain Facets can be Reused and Composed&lt;/h3&gt;

&lt;p&gt;A deployed facet can be used by many diamonds.&lt;/p&gt;

&lt;p&gt;It is possible to create and deploy a set of facets that are reused by different diamonds.&lt;/p&gt;

&lt;p&gt;The ability to use the same deployed facets for many diamonds has the potential to reduce development time, increase reliability and security, and reduce deployment costs.&lt;/p&gt;

&lt;p&gt;It is possible to implement facets in a way that makes them usable/composable/compatible with other facets.&lt;/p&gt;

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

&lt;p&gt;Diamonds implementing this ERC have the same introspection functions as ERC-2535 diamonds, so they are compatible with ERC-2535 tooling that relies on these functions.&lt;/p&gt;

&lt;p&gt;This ERC breaks compatibility with ERC-2535 events and upgrades.&lt;/p&gt;

&lt;p&gt;Facets deployed for ERC-2535 diamonds cannot be used with ERC-8153 diamonds if they do not have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; function.&lt;/p&gt;

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

&lt;h3 id=&quot;arbitrary-execution-with-upgradediamond&quot;&gt;Arbitrary Execution with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; function allows arbitrary execution with access to the diamond’s storage (through delegatecall). Access to this function must be restricted carefully.&lt;/p&gt;

&lt;h3 id=&quot;use-only-trusted-and-verified-facets&quot;&gt;Use Only Trusted and Verified Facets&lt;/h3&gt;

&lt;p&gt;Only trusted and verified facets should be added to facet-based diamonds.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pure&lt;/code&gt; and should not contain logic that varies the returned bytes. Facets should be immutable so returned selectors cannot change over time.&lt;/p&gt;

&lt;p&gt;If a facet’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; output changes, upgrades that rely on it may add/remove/replace the wrong selectors and corrupt diamonds.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-integrity-checks&quot;&gt;Upgrade Integrity Checks&lt;/h3&gt;

&lt;p&gt;The specified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;upgradeDiamond&lt;/code&gt; behavior prevents a number of upgrade mistakes. Upgrades revert when:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A facet is added that already exists in the diamond.&lt;/li&gt;
  &lt;li&gt;A facet is replaced or removed that does not exist in the diamond.&lt;/li&gt;
  &lt;li&gt;A selector is added that already exists in the diamond.&lt;/li&gt;
  &lt;li&gt;A selector is replaced that exists in the diamond but is mapped to a different facet than the facet being replaced.&lt;/li&gt;
  &lt;li&gt;A facet address contains no bytecode.&lt;/li&gt;
  &lt;li&gt;A facet does not implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exportSelectors()&lt;/code&gt; successfully.&lt;/li&gt;
  &lt;li&gt;A facet provides zero selectors.&lt;/li&gt;
  &lt;li&gt;A facet is replaced with itself (same contract address).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selector collisions (two different signatures with the same 4-byte selector) are handled as “selector already exists” and are therefore prevented.&lt;/p&gt;

&lt;h3 id=&quot;do-not-self-destruct&quot;&gt;Do Not Self Destruct&lt;/h3&gt;
&lt;p&gt;Use of selfdestruct in a facet is heavily discouraged. Misuse of it can delete a diamond or a facet.&lt;/p&gt;

&lt;h3 id=&quot;transparency&quot;&gt;Transparency&lt;/h3&gt;

&lt;p&gt;A diamond emits an event every time a facet is added, replaced or removed. Source code can be verified. This enables people and software to monitor changes to a diamond.&lt;/p&gt;

&lt;p&gt;Security and domain experts can review a diamond’s upgrade history.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sat, 07 Feb 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8153</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8153</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Modular Dispatch Proxies</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8167 - Modular Dispatch Proxies&lt;/strong&gt; is in Last Call status. It is authored by William Morriss (@wjmelements), Radek Svarz (@radeksvarz) and was originally created 2026-02-16. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8167-modular-dispatch-proxies/27781&quot;&gt;https://ethereum-magicians.org/t/erc-8167-modular-dispatch-proxies/27781&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This proposal 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.&lt;/p&gt;

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

&lt;p&gt;Proxy contracts utilizing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; 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.&lt;/p&gt;

&lt;h3 id=&quot;shared-logic-modules&quot;&gt;Shared Logic Modules&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3 id=&quot;extension&quot;&gt;Extension&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Modular designs are also appropriate for personal smart accounts such as &lt;a href=&quot;/EIPS/eip-7702&quot;&gt;EIP-7702&lt;/a&gt; EOAs.
User accounts could install features such as DEX-specific callbacks without temporarily disabling other functionality.&lt;/p&gt;

&lt;h3 id=&quot;upgrade&quot;&gt;Upgrade&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3 id=&quot;hardening&quot;&gt;Hardening&lt;/h3&gt;

&lt;p&gt;Upgradeable dispatch proxies can be permanently hardened into immutable systems by uninstalling the upgrade methods.&lt;/p&gt;

&lt;h3 id=&quot;standardization&quot;&gt;Standardization&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;p&gt;A modular dispatch proxy MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;delegatecall&lt;/code&gt; to relay the entire calldata to the delegate corresponding to the first four bytes of the calldata.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC8167&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// RECOMMENDED
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Emitted when assigning a delegate logic module to a selector
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// An address(0) delegate signals removal
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SelectorDelegated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// REQUIRED
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Returns the delegate for the selector, using address(0) for function not found
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;implementation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// REQUIRED
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Surfaces the ABI
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// SHOULD return all function selectors with implementations
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selectors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// RECOMMENDED
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// If the delegate for that selector is not set, the proxy SHOULD revert, and with FunctionNotFound.
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionNotFound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC8167&lt;/code&gt; functions SHOULD be implemented by delegates rather than in the proxy.&lt;/p&gt;

&lt;p&gt;A modular dispatch proxy constructor SHOULD configure at least one delegate.&lt;/p&gt;

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

&lt;h3 id=&quot;bytes4-selector&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4 selector&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;The most widely-supported ABI is Solidity’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.&lt;/p&gt;

&lt;h3 id=&quot;implementationbytes4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implementation(bytes4)&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;While implementations can be discovered with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth_getStorageAt&lt;/code&gt;, a common interface can support a variety of possible storage layouts and implementations.&lt;/p&gt;

&lt;p&gt;This function’s naming is consistent with monolithic proxies, but with a selector parameter.&lt;/p&gt;

&lt;h3 id=&quot;selectors&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectors()&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;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:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;For each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selector&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectors()&lt;/code&gt;, query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;implementation(selector)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;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.&lt;/li&gt;
  &lt;li&gt;Identify the functions supported by the proxy by matching its selectors with their implementation’s ABI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Although selectors are also retrievable by querying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectorDelegated&lt;/code&gt; events, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;selectors&lt;/code&gt; function provides a way to get this information without access to the logs.
Log queries can be slow without a database index.&lt;/p&gt;

&lt;p&gt;While a packed encoding would reduce memory allocation, an array of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes4&lt;/code&gt; is the simplest for tooling to decode.
It is anticipated that this method will primarily be used by tooling.&lt;/p&gt;

&lt;h3 id=&quot;upgrades&quot;&gt;Upgrades&lt;/h3&gt;

&lt;p&gt;This standard does not specify an upgrade function.
Other standards could extend this one with versioning frameworks for atomic batch upgrades.&lt;/p&gt;

&lt;h3 id=&quot;storage-layout&quot;&gt;Storage Layout&lt;/h3&gt;

&lt;p&gt;This standard does not specify a storage layout.
Other standards could suggest patterns to protect against storage collisions and other mistakes.&lt;/p&gt;

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

&lt;p&gt;This standard improves upon &lt;a href=&quot;/EIPS/eip-2535&quot;&gt;ERC-2535&lt;/a&gt; in the following ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Removal of diamond jargon.&lt;/li&gt;
  &lt;li&gt;Fewer and simpler introspection functions.&lt;/li&gt;
  &lt;li&gt;Simpler upgrade event.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Existing upgradeable monolithic proxies can upgrade to this standard using the following upgrade plan:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Upgrade to an implementation with a method to populate the selector delegate mapping.&lt;/li&gt;
  &lt;li&gt;Populate the selector delegate mapping for all methods in the ABI plus the introspection functions.&lt;/li&gt;
  &lt;li&gt;Set the implementation to a dispatch proxy using the populated selector delegate mapping.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Existing modular proxies can upgrade to this standard by adding the introspection functions and optionally emitting a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SelectorDelegated&lt;/code&gt; event for every installed function.&lt;/p&gt;

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

&lt;p&gt;The reference implementation contains three files.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;a href=&quot;/assets/eip-8167/IERC8167.sol&quot;&gt;interface&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;A namespace-based &lt;a href=&quot;/assets/eip-8167/ProxyStorageBase.sol&quot;&gt;storage layout&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;A &lt;a href=&quot;/assets/eip-8167/Proxy.sol&quot;&gt;proxy implementation&lt;/a&gt; with delegates for inspection and administration&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3 id=&quot;access-control&quot;&gt;Access control&lt;/h3&gt;

&lt;p&gt;Upgrade functions should have some form of access control.
Access control designs are outside the scope of this standard.&lt;/p&gt;

&lt;h3 id=&quot;avoid-self-destruct&quot;&gt;Avoid self-destruct&lt;/h3&gt;

&lt;p&gt;Delegates should not self-destruct.
If a delegate can self-destruct, it can break proxies that use it.&lt;/p&gt;

&lt;h3 id=&quot;storage-layout-1&quot;&gt;Storage Layout&lt;/h3&gt;

&lt;p&gt;Proxy upgrades must take care not to shift storage indices because this corrupts contract data.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The first is to define a single shared proxy storage layout in a common superclass inherited by all of the proxy’s delegates.
Such subclasses should not declare additional storage.&lt;/p&gt;

&lt;p&gt;The second is to use storage namespaces, such as &lt;a href=&quot;/EIPS/eip-7201&quot;&gt;ERC-7201&lt;/a&gt; and &lt;a href=&quot;/EIPS/eip-8042&quot;&gt;ERC-8042&lt;/a&gt;.
This approach is appropriate for shared libraries.&lt;/p&gt;

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

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

      </description>
        <pubDate>Mon, 16 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>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
  </channel>
</rss>
