<?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://ercs.ethereum.org</link>
    <atom:link href="https://ercs.ethereum.org/rss/last-call.xml" rel="self" type="application/rss+xml" />
    <lastBuildDate>Fri, 02 Oct 2026 14:54:43 +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;./eip-55.md&quot;&gt;EIP-55&lt;/a&gt; by optionally adding a chain id defined by &lt;a href=&quot;./eip-155.md&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;./eip-55.md&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;./eip-55.md&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;./eip-55.md&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;./eip-55.md&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://ercs.ethereum.org//ERCS/erc-1191</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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://ercs.ethereum.org//ERCS/erc-2266</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-2266</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;./eip-721.md&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://ercs.ethereum.org//ERCS/erc-5008</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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://ercs.ethereum.org//ERCS/erc-5114</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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://ercs.ethereum.org//ERCS/erc-5164</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-1155.md&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;./eip-1155.md&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;./eip-1155.md&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;./eip-721.md&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;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt; and &lt;a href=&quot;./eip-721.md&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;./eip-20.md&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;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt; name patterns were used due to similarities with &lt;a href=&quot;./eip-20.md&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;./eip-1155.md&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://ercs.ethereum.org//ERCS/erc-5216</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-5750.md&quot;&gt;ERC-5750&lt;/a&gt;.
Unlike a few prior art (&lt;a href=&quot;./eip-2612.md&quot;&gt;ERC-2612&lt;/a&gt; for &lt;a href=&quot;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt;, &lt;a href=&quot;./eip-4494.md&quot;&gt;ERC-4494&lt;/a&gt; for &lt;a href=&quot;./eip-721.md&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;./eip-5750.md&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;./eip-5453.md&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;./eip-5750.md&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;./eip-712.md&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;./eip-4494.md&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;./eip-5081.md&quot;&gt;ERC-5081&lt;/a&gt; is adopted, but &lt;a href=&quot;./eip-5081.md&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;eip-721.md&quot;&gt;ERC-721&lt;/a&gt;, &lt;a href=&quot;eip-1155.md&quot;&gt;ERC-1155&lt;/a&gt; and many other ERC-track EIPs. Those that aren’t, such as &lt;a href=&quot;./eip-20.md&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;./eip-4494.md&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://ercs.ethereum.org//ERCS/erc-5453</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-721.md&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;./eip-721.md&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;./eip-721.md&quot;&gt;EIP-721&lt;/a&gt;/&lt;a href=&quot;./eip-1155.md&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;./eip-1271.md&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;./eip-721.md&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;./eip-721.md&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://ercs.ethereum.org//ERCS/erc-5496</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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://ercs.ethereum.org//ERCS/erc-6224</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-721.md&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;./eip-20.md&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://ercs.ethereum.org//ERCS/erc-6357</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-6357</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;./eip-7702.md&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://ercs.ethereum.org//ERCS/erc-7744</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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://ercs.ethereum.org//ERCS/erc-7746</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-7746</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;./eip-20.md&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;./eip-20.md&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;./eip-20.md&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;./eip-20.md&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;./eip-20.md&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;./eip-20.md&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;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt; plaintext balances.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-20.md&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://ercs.ethereum.org//ERCS/erc-7945</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-2535.md&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;./eip-1538.md&quot;&gt;ERC-1538&lt;/a&gt; and &lt;a href=&quot;./eip-2535.md&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;./eip-721.md&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;./eip-8042.md&quot;&gt;ERC-8042 Diamond Storage&lt;/a&gt; and &lt;a href=&quot;./eip-7201.md&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://ercs.ethereum.org//ERCS/erc-8153</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-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;./eip-7702.md&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;./eip-2535.md&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;./eip-7201.md&quot;&gt;ERC-7201&lt;/a&gt; and &lt;a href=&quot;./eip-8042.md&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://ercs.ethereum.org//ERCS/erc-8167</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8167</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Asset Anchor Registry</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8325 - Asset Anchor Registry&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-04. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8325-asset-anchor-registry/28934&quot;&gt;https://ethereum-magicians.org/t/erc-8325-asset-anchor-registry/28934&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines interfaces for registries that
bind token contracts or token IDs to anchor records representing claims about
off-chain assets. Each anchor
contains separate commitments to a claimed legal basis and supporting evidence.
Bindings distinguish whole-contract scope from token-ID scope, enforce
registry-scoped exclusivity, and preserve immutable binding history.&lt;/p&gt;

&lt;p&gt;Token-side interfaces allow contracts to declare the same registry and anchor,
enabling consumers to verify both sides of a binding. A lifecycle interface
defines structured metadata, expiry, re-attestation, and permanent
deactivation. An optional recovery interface permits disputed bindings to be
invalidated without deleting their historical records.&lt;/p&gt;

&lt;p&gt;The resulting records provide durable, registry-scoped binding provenance for
consumers that require an auditable lifecycle history.&lt;/p&gt;

&lt;p&gt;This ERC does not establish the existence, ownership, legal validity, or value
of an off-chain asset.&lt;/p&gt;

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

&lt;p&gt;A token can claim in metadata that it represents an off-chain asset, but that
claim does not provide a common interface for another contract to determine:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;which registry record the token claims;&lt;/li&gt;
  &lt;li&gt;whether the registry records the same token-to-anchor relationship;&lt;/li&gt;
  &lt;li&gt;whether the binding is exclusive within that registry;&lt;/li&gt;
  &lt;li&gt;whether the binding applies to an entire token contract or one token ID; or&lt;/li&gt;
  &lt;li&gt;whether the anchor is active, expired, deactivated, or invalidated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deployments subject to institutional or regulatory oversight often need a
durable answer to which token tuple was recorded against an asset claim, when
the binding was established, and whether it remains current. This ERC makes
registry-scoped exclusivity and immutable binding history explicit without
asserting that the underlying claim is legally valid or factually correct.&lt;/p&gt;

&lt;p&gt;Without a mutually queryable structure, the relationship remains
assertion-only tokenization: the token can describe an off-chain asset, but an
independent consumer cannot verify the claimed token-to-record relationship
through a common interface.&lt;/p&gt;

&lt;p&gt;Applications consequently rely on implementation-specific metadata and
registries. The same asset claim can be represented differently by each issuer,
and consumers cannot inspect a binding through a common interface.&lt;/p&gt;

&lt;p&gt;This ERC standardizes the structural relationship between a registry anchor
and a token contract or token ID. The guarantee is intentionally limited to one
registry instance. Registry operators remain responsible for deciding which
claims they accept, and consumers remain responsible for deciding which
registries they trust.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;Request for Comments (RFC) 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;An &lt;strong&gt;anchor&lt;/strong&gt; is a registry record containing commitments and metadata for an
off-chain asset claim.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;contract binding&lt;/strong&gt; binds an anchor to an entire token contract. This is
appropriate when one contract represents one claimed asset or instrument.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;token-ID binding&lt;/strong&gt; binds an anchor to one token ID within a token contract.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;binding tuple&lt;/strong&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(token, bindingScope, tokenId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;valid binding&lt;/strong&gt; is a recorded binding that has not been invalidated through
the optional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetAnchorRegistryRecovery&lt;/code&gt; interface, defined in the
&lt;a href=&quot;#recovery-interface&quot;&gt;Recovery Interface&lt;/a&gt; section below. Binding validity is
distinct from lifecycle activity.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;active anchor&lt;/strong&gt; is an anchor that has not been permanently deactivated and
whose metadata has not expired.&lt;/p&gt;

&lt;h3 id=&quot;binding-scopes&quot;&gt;Binding Scopes&lt;/h3&gt;

&lt;p&gt;Implementations MUST use the following scope identifiers:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BINDING_SCOPE_CONTRACT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8325:BINDING_SCOPE:CONTRACT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BINDING_SCOPE_TOKEN_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8325:BINDING_SCOPE:TOKEN_ID&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BINDING_SCOPE_CONTRACT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokenId&lt;/code&gt; MUST equal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; as a canonical unused
value.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BINDING_SCOPE_TOKEN_ID&lt;/code&gt;, every &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; value is valid, including token ID
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;. Token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; MUST NOT be interpreted as a contract-binding sentinel.&lt;/p&gt;

&lt;h3 id=&quot;metadata-encoding&quot;&gt;Metadata Encoding&lt;/h3&gt;

&lt;p&gt;Registration metadata MUST be application binary interface (ABI) encoded as
the following ordered tuple:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorMetadata&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;jurisdiction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The canonical encoding is:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;jurisdiction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attestationDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extensions&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jurisdiction&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; and MUST NOT be later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt; MUST be later than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt; and MUST NOT
be earlier than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; at registration. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uri&lt;/code&gt; MUST NOT be empty.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extensions&lt;/code&gt; MAY be empty.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; SHOULD be a domain-separated identifier from a documented
taxonomy. When an anchor has one primary country jurisdiction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jurisdiction&lt;/code&gt;
SHOULD be a domain-separated identifier derived from its uppercase
International Organization for Standardization (ISO) 3166-1
alpha-2 code.&lt;/p&gt;

&lt;p&gt;The Uniform Resource Identifier (URI) identifies where a consumer can retrieve
material corresponding to the anchor commitments. This ERC does not require a
particular URI scheme or guarantee availability.&lt;/p&gt;

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

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boundToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;boundTokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registeredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRegistered&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokenBound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorDeactivated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorReattested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAttestationDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registerAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registerAndBind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isBound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;registration&quot;&gt;Registration&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAnchor&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; MUST reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legalHash&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The anchor identifier MUST be derived as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legalHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(legalHash, evidenceHash)&lt;/code&gt; pair therefore produces the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; within and across implementations of this ERC. A registry MUST
reject an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; that it has already registered.&lt;/p&gt;

&lt;p&gt;On successful registration, the registry MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store the supplied hashes and derived &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredAt&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorRegistered&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The mechanism for authorizing registration is implementation-defined.
Implementations MUST document their authorization policy.&lt;/p&gt;

&lt;h3 id=&quot;binding&quot;&gt;Binding&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindToken&lt;/code&gt; MUST reject an unknown anchor, an inactive or expired anchor, a zero
token address, an unsupported binding scope, and an anchor whose binding fields
have already been set.&lt;/p&gt;

&lt;p&gt;Before recording a binding, the registry MUST ensure that no valid anchor is
already associated with the same binding tuple. The uniqueness key SHOULD be
derived as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On successful binding, the registry MUST set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt;, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt; and emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBound&lt;/code&gt;. These three historical fields MUST NOT be
modified after they are set, including after deactivation or invalidation.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; MUST apply the same registration and binding requirements
atomically.&lt;/p&gt;

&lt;p&gt;The mechanism for authorizing binding is implementation-defined. It MUST
prevent an unrelated caller from binding another registrar’s unbound anchor.&lt;/p&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;token&lt;/code&gt; exposes &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorRegistry()&lt;/code&gt;, the returned address MUST equal the
registry performing the binding. A registry MAY bind a token that does not
implement a token-side interface. Such a record is a registry-side binding only
and does not constitute mutually declared binding under this ERC.&lt;/p&gt;

&lt;h3 id=&quot;registry-queries&quot;&gt;Registry Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor&lt;/code&gt; MUST return the complete stored record and MUST revert for an
unknown &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt; is not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt;, regardless
of lifecycle activity or recovery invalidation. It MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for a
known but unbound anchor and MUST revert for an unknown &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Every compliant registry MUST implement the lifecycle interface because anchor
activity and expiry are part of the common verification model:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistryLifecycle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getMetadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorMetadata&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registeredBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isActive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deactivateAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reason&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reattest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newExpiresAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAttestationDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getMetadata&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredBy&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive&lt;/code&gt; MUST revert for an unknown
anchor.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registeredBy&lt;/code&gt; MUST return the address that successfully registered the anchor
and MUST NOT change after registration.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorRecord.active&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; or if
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt; expiresAt&lt;/code&gt;. An anchor remains active at the exact
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt; timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deactivateAnchor&lt;/code&gt; MUST be restricted to authorized callers, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;active&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;, and emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt;. Manual deactivation is permanent and
MUST NOT be reversed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reattest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reattest&lt;/code&gt; MUST be restricted to an authorized caller and MUST reject a
manually deactivated anchor. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newAttestationDate&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, or earlier than the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationDate&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newExpiresAt&lt;/code&gt; MUST be later than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, later than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newAttestationDate&lt;/code&gt;, and not earlier than the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expiresAt&lt;/code&gt;. Successful
re-attestation MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorReattested&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Binding recovery is OPTIONAL. A registry that permits disputed bindings to be
invalidated MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetAnchorRegistryRecovery&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokenBindingInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bindingScope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidateTokenBinding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isBindingValid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invalidateTokenBinding&lt;/code&gt; MUST be restricted to an authorized recovery role. It
MUST reject an unknown, unbound, or previously invalidated anchor and a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reasonHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Successful invalidation MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;preserve &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bindingScope&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;boundTokenId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;make &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid(anchorId)&lt;/code&gt; return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;permanently deactivate the anchor;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt; if the anchor was active; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBindingInvalidated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An implementation MAY free the binding tuple so that a different anchor can be
bound to it. If it does so, the invalidated record MUST remain historically
queryable and MUST NOT itself be rebound.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; only when an anchor is bound and has not
been invalidated. It MUST revert for an unknown anchor.&lt;/p&gt;

&lt;h3 id=&quot;token-interfaces&quot;&gt;Token Interfaces&lt;/h3&gt;

&lt;p&gt;Whole-contract bindings use:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetBoundToken&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC165&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorRegistry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchorActive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Token-ID bindings use:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IAssetBoundTokenId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC165&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorIdOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

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

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchorActiveFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorRegistry&lt;/code&gt; MUST remain unchanged after deployment.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetBoundToken&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; MUST remain unchanged after deployment.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAssetBoundTokenId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorIdOf(tokenId)&lt;/code&gt; MUST revert when the token ID is
not bound. Once a nonzero anchor is declared for a token ID, that declaration
MUST NOT change.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchorActive&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchorActiveFor&lt;/code&gt; MUST reflect lifecycle activity from
the declared registry. Consumers MUST query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid&lt;/code&gt; separately when
the registry implements the recovery interface.&lt;/p&gt;

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

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistry).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compliant registries MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistryLifecycle).interfaceId&lt;/code&gt;. Registries implementing
recovery MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IAssetAnchorRegistryRecovery).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Compliant tokens MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the applicable token-side interface ID.&lt;/p&gt;

&lt;p&gt;ERC-165 detects interface support. It does not prove correct behavior, transfer
enforcement, registrar trustworthiness, or the validity of an off-chain claim.&lt;/p&gt;

&lt;h3 id=&quot;complete-binding-verification&quot;&gt;Complete Binding Verification&lt;/h3&gt;

&lt;p&gt;A consumer treating a binding as mutually declared MUST verify all of the
following:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor(anchorId)&lt;/code&gt; returns the expected token, scope, and token ID.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isActive(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBindingValid(anchorId)&lt;/code&gt; returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; when recovery is implemented.&lt;/li&gt;
  &lt;li&gt;The token supports the applicable token-side interface.&lt;/li&gt;
  &lt;li&gt;The token reports the same registry and anchor.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Failure of any applicable check means the consumer MUST NOT treat the binding
as a current mutually declared binding.&lt;/p&gt;

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

&lt;h3 id=&quot;why-use-a-registry&quot;&gt;Why Use a Registry?&lt;/h3&gt;

&lt;p&gt;A separate registry allows the same binding interface to compose with fungible,
non-fungible, multi-token, permissioned, and future token standards. It also
provides one inspection surface for applications that do not control the token
implementation.&lt;/p&gt;

&lt;p&gt;The registry does not create global truth. Consumers select which registry
operators and authorization policies they trust.&lt;/p&gt;

&lt;h3 id=&quot;why-two-hashes&quot;&gt;Why Two Hashes?&lt;/h3&gt;

&lt;p&gt;Off-chain asset structures often distinguish the instrument or legal basis
from evidence about the referenced asset. Separate commitments preserve that
distinction without assigning universal semantics to either document set.&lt;/p&gt;

&lt;p&gt;Deployments that do not need the distinction can commit to two separately
defined records. A zero hash is not available as an omission sentinel.&lt;/p&gt;

&lt;h3 id=&quot;why-a-deterministic-anchor-identifier&quot;&gt;Why a Deterministic Anchor Identifier?&lt;/h3&gt;

&lt;p&gt;Deriving &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; from both commitments gives implementations the same
identifier for the same pair of bytes and makes duplicate registration within a
registry unambiguous. It does not deduplicate semantically equivalent documents
with different byte representations.&lt;/p&gt;

&lt;h3 id=&quot;why-explicit-binding-scope&quot;&gt;Why Explicit Binding Scope?&lt;/h3&gt;

&lt;p&gt;Using token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; to mean whole-contract binding prevents token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; from
being bound as an actual &lt;a href=&quot;./eip-721.md&quot;&gt;ERC-721&lt;/a&gt; or
&lt;a href=&quot;./eip-1155.md&quot;&gt;ERC-1155&lt;/a&gt; token. Including an explicit scope makes contract
binding and token-ID-zero binding distinct.&lt;/p&gt;

&lt;h3 id=&quot;why-split-the-token-interfaces&quot;&gt;Why Split the Token Interfaces?&lt;/h3&gt;

&lt;p&gt;A whole-contract token has no meaningful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorIdOf&lt;/code&gt; query, while a collection
with independently anchored token IDs has no meaningful contract-wide
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt;. Separate interfaces avoid mandatory functions with misleading or
implementation-specific failure behavior.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-activity-from-binding&quot;&gt;Why Separate Activity from Binding?&lt;/h3&gt;

&lt;p&gt;A binding is historical identity data. Activity is lifecycle status. Expiry or
deactivation can make an anchor operationally inactive without changing which
token was bound to it. Accordingly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isBound&lt;/code&gt; is not an activity check.&lt;/p&gt;

&lt;h3 id=&quot;why-an-optional-recovery-interface&quot;&gt;Why an Optional Recovery Interface?&lt;/h3&gt;

&lt;p&gt;Permanent bindings are vulnerable to registrar compromise, key loss, and
binding-key squatting. Recovery allows an explicitly trusted administrator to
invalidate an operational binding while preserving its history. Deployments
that prefer absolute immutability can omit the recovery interface.&lt;/p&gt;

&lt;p&gt;Recovery introduces substantial administrative trust and is therefore not part
of the minimum registry interface.&lt;/p&gt;

&lt;h3 id=&quot;why-not-enforce-allocation-integrity&quot;&gt;Why Not Enforce Allocation Integrity?&lt;/h3&gt;

&lt;p&gt;Allocation constraints, such as ensuring that fractional token supply does not
represent more than a defined share of an asset, depend on the economic and
legal structure of the instrument. They are meaningful for some fungible
fractional claims but not for a single non-fungible token (NFT) representing one
object or for a registry record that does not express ownership percentages.&lt;/p&gt;

&lt;p&gt;The registry therefore standardizes binding identity rather than issuance or
allocation rules. Tokens and application-specific contracts remain responsible
for enforcing any supply, fraction, or entitlement constraints.&lt;/p&gt;

&lt;h3 id=&quot;why-leave-registry-governance-open&quot;&gt;Why Leave Registry Governance Open?&lt;/h3&gt;

&lt;p&gt;Different deployments require different trust models. A registry may be
operated by one accountable issuer, a regulated registrar, a multisignature, a
decentralized autonomous organization (DAO), or a permissionless protocol.
Requiring one governance model would exclude
otherwise interoperable implementations without making their off-chain claims
more truthful.&lt;/p&gt;

&lt;p&gt;Consumers select which registries and governance policies they trust. The
common interface makes those registries technically inspectable; it does not
make them equally trustworthy.&lt;/p&gt;

&lt;h3 id=&quot;why-are-historical-binding-fields-immutable&quot;&gt;Why Are Historical Binding Fields Immutable?&lt;/h3&gt;

&lt;p&gt;Changing a binding’s token, scope, or token ID in place would erase the
relationship that consumers previously inspected. This ERC therefore preserves
those fields after deactivation and recovery invalidation, allowing auditors
and other consumers to determine which tuple was recorded and how its status
changed over time.&lt;/p&gt;

&lt;p&gt;Field immutability does not mean that a binding remains active or valid.
Consumers must evaluate lifecycle activity and, when implemented, recovery
validity separately. If an implementation releases an invalidated tuple, the
invalidated record remains queryable and a replacement is stored as a separate
anchor. The guarantee remains scoped to one registry and does not establish
global one-token-to-one-asset uniqueness.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;./eip-3643.md&quot;&gt;ERC-3643&lt;/a&gt; and &lt;a href=&quot;./eip-7943.md&quot;&gt;ERC-7943&lt;/a&gt; define token behavior and
compliance-related interfaces. They do not define the registry-scoped
token-to-anchor relationship specified here. Tokens implementing either can
also implement a token-side interface from this ERC.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces new interfaces and does not change existing token
standards. Existing token contracts can be recorded in a registry without
modification, but this produces only a registry-side binding.&lt;/p&gt;

&lt;p&gt;An existing upgradeable token can add the applicable token-side interface. An
immutable token that lacks the interface requires a wrapper, adapter, or new
deployment to provide mutually declared binding. Consumers should distinguish a
registry-only record from a binding confirmed by both registry and token.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least the following cases:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;deterministic anchor derivation and duplicate rejection;&lt;/li&gt;
  &lt;li&gt;rejection of zero hashes and malformed metadata;&lt;/li&gt;
  &lt;li&gt;contract scope with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tokenId == 0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;rejection of contract scope with a nonzero token ID;&lt;/li&gt;
  &lt;li&gt;token-ID scope with token ID &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;separation of contract scope from token-ID-zero scope;&lt;/li&gt;
  &lt;li&gt;rejection of duplicate anchor and duplicate valid binding tuple use;&lt;/li&gt;
  &lt;li&gt;atomic registration and binding;&lt;/li&gt;
  &lt;li&gt;expiry at, before, and after the inclusive boundary;&lt;/li&gt;
  &lt;li&gt;permanent manual deactivation;&lt;/li&gt;
  &lt;li&gt;monotonic re-attestation;&lt;/li&gt;
  &lt;li&gt;token registry mismatch;&lt;/li&gt;
  &lt;li&gt;complete mutually declared binding verification across registry and
token-side queries;&lt;/li&gt;
  &lt;li&gt;preservation of binding fields across deactivation and recovery invalidation;&lt;/li&gt;
  &lt;li&gt;lifecycle event coverage for registration, binding, re-attestation,
deactivation, and recovery invalidation;&lt;/li&gt;
  &lt;li&gt;optional release of an invalidated binding tuple; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A Solidity reference implementation, unit tests, fuzz tests, invariants, and an
independent audit are linked from the discussion referenced in the preamble.
The implementation is illustrative; its access-control roles and deployment
model are not required by this ERC.&lt;/p&gt;

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

&lt;h3 id=&quot;registry-trust&quot;&gt;Registry Trust&lt;/h3&gt;

&lt;p&gt;The registry proves only that its own state satisfies the specified structural
rules. A malicious or compromised registrar can register false claims with
validly formed hashes and metadata. Consumers should evaluate the registry’s
operator, authorization policy, upgrade authority, and legal context.&lt;/p&gt;

&lt;h3 id=&quot;no-legal-or-physical-truth-guarantee&quot;&gt;No Legal or Physical Truth Guarantee&lt;/h3&gt;

&lt;p&gt;Neither a hash nor a mutually declared token binding proves that an off-chain
asset exists, that documents are authentic, or that a token conveys a legal
right. Those determinations require external verification.&lt;/p&gt;

&lt;h3 id=&quot;registration-to-binding-races&quot;&gt;Registration-to-Binding Races&lt;/h3&gt;

&lt;p&gt;Separate registration and binding create an interval in which an unauthorized
caller may attempt to bind an anchor. Implementations should restrict binding to
authorized parties. Registrars should use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;registerAndBind&lt;/code&gt; when atomicity is
required.&lt;/p&gt;

&lt;h3 id=&quot;malicious-tokens-and-interface-spoofing&quot;&gt;Malicious Tokens and Interface Spoofing&lt;/h3&gt;

&lt;p&gt;A token can return arbitrary values from the token-side interfaces or falsely
claim ERC-165 support. Consumers should verify the registry record independently.
Registries that call token contracts during binding should use static calls and
handle malformed return data and reverts.&lt;/p&gt;

&lt;h3 id=&quot;recovery-authority&quot;&gt;Recovery Authority&lt;/h3&gt;

&lt;p&gt;A recovery administrator can invalidate legitimate bindings and, when the
implementation releases binding tuples, enable replacement anchors. Production
deployments should protect recovery authority with a multisignature,
governance, timelock, or equivalent controls. Consumers should monitor
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TokenBindingInvalidated&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AnchorDeactivated&lt;/code&gt; events.&lt;/p&gt;

&lt;p&gt;Releasing an invalidated tuple does not change an immutable token-side anchor
declaration. A replacement can be mutually declared only when the token already
declares the replacement anchor. A replacement binding recorded for a token that
does not expose a token-side interface is registry-side only.&lt;/p&gt;

&lt;h3 id=&quot;document-canonicalization&quot;&gt;Document Canonicalization&lt;/h3&gt;

&lt;p&gt;The registry treats &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;legalHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt; as opaque commitments. Two
representations of the same document can produce different hashes. Deployments
requiring interoperable document commitments should define a deterministic
normalization and bundle-hashing procedure.&lt;/p&gt;

&lt;h3 id=&quot;data-availability&quot;&gt;Data Availability&lt;/h3&gt;

&lt;p&gt;An on-chain commitment is not useful for verification if the committed material
cannot be retrieved. The registry does not guarantee URI persistence or data
availability. Deployments should use durable storage and availability policies.&lt;/p&gt;

&lt;h3 id=&quot;multi-registry-and-cross-chain-duplication&quot;&gt;Multi-Registry and Cross-Chain Duplication&lt;/h3&gt;

&lt;p&gt;Independent registries or deployments on different chains can register claims
about the same off-chain asset. This ERC provides no global uniqueness or
cross-registry conflict resolution.&lt;/p&gt;

&lt;p&gt;Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; does not include a chain identifier or registry address,
consumers requiring globally scoped identity should use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(chainId, registry, anchorId)&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; alone. A companion system
that accepts only a bare &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorId&lt;/code&gt; can otherwise conflate records from
different registry domains.&lt;/p&gt;

&lt;h3 id=&quot;expiry-and-timestamp-dependence&quot;&gt;Expiry and Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Lifecycle status depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, which block producers can vary
within protocol constraints. Applications should avoid relying on second-level
precision around an expiry boundary.&lt;/p&gt;

&lt;h3 id=&quot;upgradeability&quot;&gt;Upgradeability&lt;/h3&gt;

&lt;p&gt;An upgradeable registry can alter binding behavior after consumers begin
relying on it. Upgrades must preserve historical binding fields to remain
compliant. Consumers should inspect proxy administration and upgrade policies.&lt;/p&gt;

&lt;h3 id=&quot;institutional-and-regulated-deployments&quot;&gt;Institutional and Regulated Deployments&lt;/h3&gt;

&lt;p&gt;Deployments operating under institutional or regulatory controls should
document registration and binding authority, protect recovery and upgrade
authority with appropriate multisignature, timelock, governance, or equivalent
controls, and monitor all binding and lifecycle events.&lt;/p&gt;

&lt;p&gt;Such deployments should also define how contested invalidations are reviewed
and how committed records are made available to authorized auditors. Conformance
with this ERC provides a common technical interface; it does not establish
regulatory status, legal sufficiency, or compliance with any jurisdiction’s
requirements.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sat, 04 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8325</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8325</guid>
      </item>
      
    
      
      
      <item>
        <title>Canonical Document Bundle Anchor</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8326 - Canonical Document Bundle Anchor&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8326-canonical-document-bundle-anchor/28935&quot;&gt;https://ethereum-magicians.org/t/erc-8326-canonical-document-bundle-anchor/28935&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines a deterministic manifest and
anchoring interface for commitments to bundles of off-chain documents. Each
document is represented by
a fixed-width entry containing a content hash, document role, media-type hash,
filename hash, and normalization-profile identifier. Entries are placed in a
total order and hashed under a schema-version prefix to produce one &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt;
bundle commitment.&lt;/p&gt;

&lt;p&gt;The on-chain interface anchors a bundle hash in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; namespace,
records declarative metadata, and preserves an append-only supersession history.
An optional recovery interface permits administrative reassignment of authority
over a contested namespace without rewriting anchored records.&lt;/p&gt;

&lt;p&gt;This ERC standardizes manifest construction and commitment anchoring. It does
not prove document authenticity, legal effect, off-chain availability, or the
correct application of a normalization profile.&lt;/p&gt;

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

&lt;p&gt;Contracts and applications frequently commit to multiple off-chain documents,
including agreements, certifications, evidence, amendments, and supporting
records. Without a common manifest, implementations differ in entry encoding,
ordering, version separation, and supersession behavior. Two systems can hold
the same canonical document representations but derive incompatible bundle
commitments.&lt;/p&gt;

&lt;p&gt;Document commitment has two distinct layers. Normalization transforms a raw
format into canonical bytes. Manifesting describes and orders the resulting
document commitments before deriving a bundle hash. Normalization is
format-specific and evolves independently; manifesting and on-chain anchoring
can remain stable.&lt;/p&gt;

&lt;p&gt;This ERC provides a common manifest and anchoring surface while making that
boundary explicit. Compatible implementations derive the same bundle hash only
when they use the same canonical document bytes, entry fields, normalization
profile identifiers, schema version, and ordering rules.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;document entry&lt;/strong&gt; is a fixed-width record describing one normalized document
commitment.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;normalization profile&lt;/strong&gt; defines how raw document input is converted to the
bytes committed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;bundle&lt;/strong&gt; is a non-empty multiset of document entries. Duplicate entries are
retained and affect the resulting bundle hash.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;bundle hash&lt;/strong&gt; is the schema-versioned commitment derived from the canonically
ordered entries.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;slot&lt;/strong&gt; is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; namespace containing at most one active
bundle hash.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;superseded record&lt;/strong&gt; is a historical anchor that has been replaced in its
slot. Supersession does not delete or rewrite its immutable fields.&lt;/p&gt;

&lt;h3 id=&quot;document-entry&quot;&gt;Document Entry&lt;/h3&gt;

&lt;p&gt;Each document MUST be represented as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mimeTypeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filenameHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt; MUST be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; hash of the exact output bytes produced by
the selected normalization profile.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt; identifies the function of the document within the bundle.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mimeTypeHash&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; of the canonical IANA media type encoded as
lowercase ASCII without parameters. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;application/json;
charset=utf-8&lt;/code&gt; is represented by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&quot;application/json&quot;)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filenameHash&lt;/code&gt; MUST be derived by treating U+002F (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;) and U+005C (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;) as
path separators, retaining the substring after the final separator, applying
ASCII lowercase conversion to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Z&lt;/code&gt;, applying Unicode NFC
normalization, encoding the result as UTF-8, and applying &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normProfileId&lt;/code&gt; identifies the transformation used to produce the committed
bytes. Consumers MUST NOT interpret &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt; without considering its
normalization profile.&lt;/p&gt;

&lt;h3 id=&quot;schema-role-and-profile-identifiers&quot;&gt;Schema, Role, and Profile Identifiers&lt;/h3&gt;

&lt;p&gt;Implementations MUST use the following schema identifier:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SCHEMA_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8326:BUNDLE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The following role identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LEGAL_BASIS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LEGAL_BASIS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVIDENCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EVIDENCE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CERTIFICATION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CERTIFICATION&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AGREEMENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AGREEMENT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AMENDMENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;AMENDMENT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUPPORTING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SUPPORTING&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MAY define additional role identifiers. Custom roles SHOULD use a
documented namespace and version to prevent semantic collisions.&lt;/p&gt;

&lt;p&gt;The following normalization profiles are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_RAW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:RAW:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_JSON_RFC8785&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:JSON:RFC8785:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PROFILE_XML_C14N11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;NORM:XML:C14N11:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt;, the output bytes are the raw input bytes without
transformation.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_JSON_RFC8785&lt;/code&gt;, the output bytes are the UTF-8 serialization
produced by &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8785&quot;&gt;RFC 8785&lt;/a&gt;. Implementations
MUST reject inputs that cannot be processed under the RFC 8785 and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc7493&quot;&gt;I-JSON&lt;/a&gt; constraints, including
duplicate object keys, invalid Unicode, lone surrogates, and numbers outside
the interoperable range. JSON string values are preserved;
this profile does not apply Unicode normalization to them.&lt;/p&gt;

&lt;p&gt;For &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_XML_C14N11&lt;/code&gt;, the output bytes are produced by
&lt;a href=&quot;https://www.w3.org/TR/2008/REC-xml-c14n11-20080502/&quot;&gt;Canonical XML 1.1&lt;/a&gt;
without comments. Implementations MUST disable external entity resolution.
This profile is distinct from Exclusive XML Canonicalization.&lt;/p&gt;

&lt;p&gt;PDF, image, signed-PDF, and plain-text normalization are not defined by this
ERC. Such documents SHOULD use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt; unless another precisely specified
profile is agreed by the producer and verifier.&lt;/p&gt;

&lt;p&gt;Custom profile identifiers SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NORM:CUSTOM:&amp;lt;namespace&amp;gt;:&amp;lt;format&amp;gt;:&amp;lt;version&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A custom profile specification MUST define exact transformation rules and test
fixtures. The namespace MUST identify the defining organization or protocol.&lt;/p&gt;

&lt;h3 id=&quot;canonical-ordering&quot;&gt;Canonical Ordering&lt;/h3&gt;

&lt;p&gt;Entries MUST be ordered lexicographically by their raw &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; values using
the following keys, each ascending:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filenameHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contentHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mimeTypeHash&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;normProfileId&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The comparison proceeds to the next key only when all preceding keys are equal.
Equal entries remain duplicated. No timestamp or preparer-controlled value is
included in a document entry.&lt;/p&gt;

&lt;h3 id=&quot;bundle-hash-derivation&quot;&gt;Bundle Hash Derivation&lt;/h3&gt;

&lt;p&gt;A bundle MUST contain at least one entry.&lt;/p&gt;

&lt;p&gt;For each canonically ordered entry, derive:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mimeTypeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filenameHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;entry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;normProfileId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The bundle hash is:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SCHEMA_V1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leaf1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leafN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All encoded elements are fixed-width &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; values, so packed encoding does
not introduce variable-length boundary ambiguity.&lt;/p&gt;

&lt;p&gt;Future incompatible manifest schemas MUST use a new schema identifier. They
MUST NOT reuse &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCHEMA_V1&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;reference-hashing-functions&quot;&gt;Reference Hashing Functions&lt;/h3&gt;

&lt;p&gt;The following signatures describe two conforming reference paths:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeCanonicalBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;computeBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DocumentEntry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;pure&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeCanonicalBundleHash&lt;/code&gt; MUST sort entries according to the total order
before deriving the hash.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeBundleHash&lt;/code&gt; MUST require already sorted entries and MUST revert for
unsorted input. Both functions MUST revert for an empty bundle and MUST produce
the derivation specified above.&lt;/p&gt;

&lt;p&gt;The reference &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeCanonicalBundleHash&lt;/code&gt; uses an in-memory quadratic sort for
clarity. Production systems SHOULD normalize, sort, and hash off-chain. Large
bundles verified on-chain SHOULD use pre-sorted entries with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;computeBundleHash&lt;/code&gt; or a more gas-efficient algorithm that produces the same
total order.&lt;/p&gt;

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

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDocumentBundleAnchor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchoredBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchoredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;superseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersededBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BundleAnchored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BundleSuperseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;anchorBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersedeBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newBundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAnchor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnchorRecord&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAnchored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bundleHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activeBundle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;anchoring&quot;&gt;Anchoring&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundleHash&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, or
zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadataURI&lt;/code&gt; MAY be empty. An empty value indicates that the anchor does not
provide an on-chain retrieval pointer. Applications requiring availability
SHOULD enforce a non-empty URI before calling the registry.&lt;/p&gt;

&lt;p&gt;Applications without an existing subject identifier SHOULD derive a nonzero,
domain-separated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; from application context rather than sharing a
common placeholder value.&lt;/p&gt;

&lt;p&gt;Each record MUST be keyed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(bundleHash, subjectId, role)&lt;/code&gt; triple. The same
bundle hash MAY be anchored under different subjects or roles, producing
independent records.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject a duplicate triple and MUST reject a slot that already
has an active bundle. Replacement of an occupied slot MUST use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeBundle&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, the registry MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store all supplied values;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersededBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set the active bundle for the slot; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleAnchored&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The registry MUST restrict anchoring to authorized callers. Its authorization
mechanism is implementation-defined and MUST be documented.&lt;/p&gt;

&lt;h3 id=&quot;supersession&quot;&gt;Supersession&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeBundle&lt;/code&gt; MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newBundleHash&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt;. It MUST reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldBundleHash ==
newBundleHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The old record MUST exist, MUST NOT already be superseded, and MUST be the active
bundle for the specified slot. The new triple MUST NOT already exist.&lt;/p&gt;

&lt;p&gt;The caller MUST be authorized to supersede that slot. Authorization is
implementation-defined, but an unrelated authorized anchorer MUST NOT be able to
take over another principal’s slot.&lt;/p&gt;

&lt;p&gt;Supersession MUST atomically:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set the old record’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; field to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set its &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersededBy&lt;/code&gt; field to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newBundleHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;create the new active record;&lt;/li&gt;
  &lt;li&gt;update the active slot;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleSuperseded&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BundleAnchored&lt;/code&gt; for the new record.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The old record’s remaining fields MUST NOT change and the old record MUST remain
queryable.&lt;/p&gt;

&lt;h3 id=&quot;queries&quot;&gt;Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor&lt;/code&gt; MUST return the complete record for a triple and MUST revert when no
record exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isAnchored&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for every existing record, including a
superseded record, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for an unknown triple.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeBundle&lt;/code&gt; MUST return the active bundle hash for a slot or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; if
the slot has never been occupied.&lt;/p&gt;

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

&lt;p&gt;Administrative slot recovery is OPTIONAL. A registry that supports principal
reassignment MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IDocumentBundleAnchorRecovery&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SlotPrincipalAssigned&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;principal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;slotPrincipal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assignSlotPrincipal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;principal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;slotPrincipal&lt;/code&gt; MUST return the address currently authorized as principal for
the slot or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address(0)&lt;/code&gt; when none is assigned.&lt;/p&gt;

&lt;p&gt;When the recovery extension is implemented, successful first anchoring and
supersession MUST set the slot principal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assignSlotPrincipal&lt;/code&gt; MUST be restricted to an authorized recovery
administrator and MUST reject zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt;, and a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;principal&lt;/code&gt;. Assignment MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SlotPrincipalAssigned&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Principal assignment does not itself grant general anchoring authority. A
designated principal MUST also satisfy the implementation’s authorization
policy before anchoring or superseding.&lt;/p&gt;

&lt;p&gt;If a principal is assigned before first anchoring, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchorBundle&lt;/code&gt; MUST reject
any other caller for that slot. After reassignment, the former principal MUST
NOT be able to supersede that slot solely by retaining general anchoring
authority.&lt;/p&gt;

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

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IDocumentBundleAnchor).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registries implementing recovery MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IDocumentBundleAnchorRecovery).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 reports interface support. It does not establish that a bundle was
derived correctly, that referenced documents are authentic or available, or
that an operator is trustworthy.&lt;/p&gt;

&lt;h3 id=&quot;consumer-verification&quot;&gt;Consumer Verification&lt;/h3&gt;

&lt;p&gt;A consumer relying on an active bundle MUST:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Query &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeBundle(subjectId, role)&lt;/code&gt; and reject &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Retrieve the corresponding record with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAnchor(bundleHash, subjectId, role)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Verify that the returned fields match the requested hash, subject, and role.&lt;/li&gt;
  &lt;li&gt;Verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;anchoredAt&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; are nonzero.&lt;/li&gt;
  &lt;li&gt;Verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;superseded&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Reproduce the manifest, canonical ordering, and bundle hash off-chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; is declarative and MUST NOT be treated as independently verified
by the anchoring contract.&lt;/p&gt;

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

&lt;h3 id=&quot;why-separate-manifesting-from-normalization&quot;&gt;Why Separate Manifesting from Normalization?&lt;/h3&gt;

&lt;p&gt;Combining universal document normalization with bundle hashing would overstate
what one ERC can guarantee. The manifest gives normalized document commitments
a common structure. Profiles define how a particular input format produces the
committed bytes and can evolve independently.&lt;/p&gt;

&lt;h3 id=&quot;why-a-total-order-over-all-five-fields&quot;&gt;Why a Total Order Over All Five Fields?&lt;/h3&gt;

&lt;p&gt;Ordering by only role, filename, and content leaves insertion order as a hidden
tie-breaker when entries differ only by media type or normalization profile.
Including all five fields gives every distinct entry a deterministic position.&lt;/p&gt;

&lt;h3 id=&quot;why-include-a-schema-identifier&quot;&gt;Why Include a Schema Identifier?&lt;/h3&gt;

&lt;p&gt;The schema identifier separates incompatible manifest versions. Without it, a
future change to entry interpretation or hash derivation could reuse the same
hash domain.&lt;/p&gt;

&lt;h3 id=&quot;why-use-subject-and-role-slots&quot;&gt;Why Use Subject and Role Slots?&lt;/h3&gt;

&lt;p&gt;The same document set can be relevant to multiple subjects or serve different
purposes. Keying records by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(bundleHash, subjectId, role)&lt;/code&gt; preserves those
independent records, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, role)&lt;/code&gt; identifies the one current bundle
for a particular purpose.&lt;/p&gt;

&lt;h3 id=&quot;why-permit-an-empty-metadata-uri&quot;&gt;Why Permit an Empty Metadata URI?&lt;/h3&gt;

&lt;p&gt;The bundle commitment remains valid without an on-chain retrieval pointer. Some
deployments distribute documents through private or regulated channels, while
others use content-addressed public storage. Availability policy belongs to the
application and is not implied by a syntactically non-empty URI.&lt;/p&gt;

&lt;h3 id=&quot;why-preserve-superseded-records&quot;&gt;Why Preserve Superseded Records?&lt;/h3&gt;

&lt;p&gt;Document sets evolve through amendments, renewals, and corrections. Mutating or
deleting the prior record would remove the audit trail. Supersession changes
only the prior record’s forward pointer and status.&lt;/p&gt;

&lt;h3 id=&quot;why-a-slot-principal-recovery-extension&quot;&gt;Why a Slot-Principal Recovery Extension?&lt;/h3&gt;

&lt;p&gt;An anchoring key can be compromised, revoked, or used to squat a slot. Directly
attempting an administrative supersession is front-runnable because the current
principal can supersede first and invalidate the administrator’s expected old
hash. Atomic principal reassignment removes that race while preserving all
bundle records.&lt;/p&gt;

&lt;p&gt;Recovery introduces administrative trust, so it is separated from the core
interface. Deployments preferring immutable authority can omit it.&lt;/p&gt;

&lt;h3 id=&quot;why-compute-bundle-hashes-off-chain&quot;&gt;Why Compute Bundle Hashes Off-Chain?&lt;/h3&gt;

&lt;p&gt;Normalization and sorting can be expensive. The reference canonical convenience
path uses a quadratic sort and repeated memory encoding, which is suitable for
tests and small bundles but inefficient for large on-chain sets. The anchoring
contract accepts a precomputed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundleHash&lt;/code&gt;; consumers reproduce it off-chain.&lt;/p&gt;

&lt;h3 id=&quot;why-not-use-a-merkle-root&quot;&gt;Why Not Use a Merkle Root?&lt;/h3&gt;

&lt;p&gt;This ERC commits to the complete ordered manifest and is optimized for
reproducing one bundle identifier, not proving membership of a single document
without the rest of the manifest. Applications requiring compact membership
proofs can commit a separately specified Merkle root as a document or extension
field, but that construction is outside this ERC.&lt;/p&gt;

&lt;h3 id=&quot;why-defer-pdf-and-image-normalization&quot;&gt;Why Defer PDF and Image Normalization?&lt;/h3&gt;

&lt;p&gt;PDF and image files contain format-specific metadata, incremental updates,
compression choices, object ordering, color profiles, and renderer-dependent
behavior. A credible profile requires exact binary fixtures and specialized
review. Until then, byte-identical raw hashing is the only defined profile for
those files.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;./eip-5732.md&quot;&gt;ERC-5732&lt;/a&gt; defines a generic commit-reveal mechanism. It can be
used as a privacy layer around publication but does not define document entries
or bundle hashing.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-7208.md&quot;&gt;ERC-7208&lt;/a&gt; defines general on-chain data containers. This ERC
defines a document-specific commitment and lifecycle interface.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-7578.md&quot;&gt;ERC-7578&lt;/a&gt; includes document URI storage in a physical-asset
redemption flow but does not define deterministic bundle manifesting.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-3668.md&quot;&gt;ERC-3668&lt;/a&gt; defines an off-chain data retrieval and verification
flow. It can retrieve material referenced by an anchor but does not determine
how a document bundle commitment is derived.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces new interfaces and does not change existing token or
registry standards. Existing systems can store the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; bundle
hash without changing their storage type, but ad hoc bundle hashes are not
necessarily compatible with this derivation.&lt;/p&gt;

&lt;p&gt;Existing document registries can integrate by storing this bundle hash as a
document commitment or by deploying a companion &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IDocumentBundleAnchor&lt;/code&gt;
registry. Composition with any particular asset registry is optional;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; is an application-defined nonzero identifier.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;raw-byte content hashing;&lt;/li&gt;
  &lt;li&gt;RFC 8785 canonical serialization and invalid-input rejection;&lt;/li&gt;
  &lt;li&gt;Canonical XML 1.1 serialization with external entities disabled;&lt;/li&gt;
  &lt;li&gt;all profile, role, and schema constants;&lt;/li&gt;
  &lt;li&gt;ordering differences at each of the five fields;&lt;/li&gt;
  &lt;li&gt;permutation independence through the canonical hashing path;&lt;/li&gt;
  &lt;li&gt;rejection of unsorted input through the pre-sorted path;&lt;/li&gt;
  &lt;li&gt;empty, single-entry, and duplicate-entry bundles;&lt;/li&gt;
  &lt;li&gt;schema-version separation;&lt;/li&gt;
  &lt;li&gt;anchoring and querying independent triples;&lt;/li&gt;
  &lt;li&gt;rejection of occupied active slots;&lt;/li&gt;
  &lt;li&gt;multi-step supersession history;&lt;/li&gt;
  &lt;li&gt;independent use of the same bundle hash by different subjects or roles;&lt;/li&gt;
  &lt;li&gt;empty and non-empty metadata URIs;&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection; and&lt;/li&gt;
  &lt;li&gt;contested-slot recovery and pre-assignment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;normative-test-vectors&quot;&gt;Normative Test Vectors&lt;/h3&gt;

&lt;p&gt;The hexadecimal byte strings in this section are authoritative. Text renderings
are included only for readability. None of the inputs or canonical outputs has
an implicit byte-order mark or trailing newline unless its hexadecimal form
includes one.&lt;/p&gt;

&lt;p&gt;The schema identifier for these vectors is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SCHEMA_V1
0x1853dddb0c73884633f2ff8e736679ec654a11f704ed868aacca79d8ae4caf67
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;json-entry&quot;&gt;JSON Entry&lt;/h4&gt;

&lt;p&gt;The filename input contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;e&lt;/code&gt; followed by U+0301 COMBINING ACUTE ACCENT.
Filename processing selects the basename, folds ASCII uppercase characters,
and applies NFC, producing the UTF-8 bytes for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;café.json&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       {&quot;b&quot;:2,&quot;a&quot;:1}
input bytes:          0x7b2262223a322c2261223a317d
canonical document:   {&quot;a&quot;:1,&quot;b&quot;:2}
canonical bytes:      0x7b2261223a312c2262223a327d
filename input:       records/Cafe\u0301.JSON
filename input bytes: 0x7265636f7264732f43616665cc812e4a534f4e
canonical filename:   café.json
filename bytes:       0x636166c3a92e6a736f6e
role preimage:         AGREEMENT
media type preimage:  application/json
profile preimage:     NORM:JSON:RFC8785:V1
contentHash:          0xb8ffb64722137f4b100665a52e3c943f8066e8ab8ba3b427e6f4b404defd82b0
role:                 0x566614d5b403a4ea71e1ef1027b77ff1e1a13a54c7f393aa64a1368de23a5f92
mimeTypeHash:         0x82e6a468c95da6cfe399f69ee0782fd009e354a8030ea5636ea9c7db0edcf7f5
filenameHash:         0x3b40ecd25f3375868ddf559a0ef47c2dc15863a529ac592bec5e1b618bcbaf3e
normProfileId:        0x464861b0846e795db3d9c52e9c49870c7e83f2bb07f73764f7e4850151994f40
leaf:                 0xe78934e3ee972b7eae660a945de9780c77e5656203bfe437ab117413adf3ad2b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;xml-entry&quot;&gt;XML Entry&lt;/h4&gt;

&lt;p&gt;The backslash in the filename input is a path separator. Canonical XML 1.1
orders the unqualified attributes lexicographically. The canonical output has
no trailing newline.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       &amp;lt;doc b=&quot;2&quot; a=&quot;1&quot;&amp;gt;&amp;lt;/doc&amp;gt;
input bytes:          0x3c646f6320623d22322220613d2231223e3c2f646f633e
canonical document:   &amp;lt;doc a=&quot;1&quot; b=&quot;2&quot;&amp;gt;&amp;lt;/doc&amp;gt;
canonical bytes:      0x3c646f6320613d22312220623d2232223e3c2f646f633e
filename input:       Evidence\Proof.XML
filename input bytes: 0x45766964656e63655c50726f6f662e584d4c
canonical filename:   proof.xml
filename bytes:       0x70726f6f662e786d6c
role preimage:         EVIDENCE
media type preimage:  application/xml
profile preimage:     NORM:XML:C14N11:V1
contentHash:          0xde64c753c807c4620bf010c7e855bcd38bd389e980c4054b81abd5d44d45eab1
role:                 0x7477535acdef313b25d16b4871e7023fac62af68d6312bbdbdb96203a4710dc3
mimeTypeHash:         0x37aaf14a93fea5695fd8577aacfb548c98692a106d439219bfb9b83e3011ea2f
filenameHash:         0x696b36bf7095c1b1564382a37b8f5ba7d259b36be7639a7a1b50c97cd13cfe39
normProfileId:        0x72efa7a47196f4ad021a5a3758b19b14d8e09d7b7b211bf4745b35cba62e49c2
leaf:                 0x8c72daea8a7297c8d307dd41e24038ff71065f9b0932a07e9016942abbc5c9ac
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;raw-entry&quot;&gt;Raw Entry&lt;/h4&gt;

&lt;p&gt;The input and canonical output end with one U+000A LINE FEED byte.&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;input document:       Hello, ERC-8326!&amp;lt;LF&amp;gt;
input bytes:          0x48656c6c6f2c204552432d38333236210a
canonical document:   Hello, ERC-8326!&amp;lt;LF&amp;gt;
canonical bytes:      0x48656c6c6f2c204552432d38333236210a
filename input:       README.TXT
filename input bytes: 0x524541444d452e545854
canonical filename:   readme.txt
filename bytes:       0x726561646d652e747874
role preimage:         SUPPORTING
media type preimage:  text/plain
profile preimage:     NORM:RAW:V1
contentHash:          0x06750728a91d155294f77f992fec49acabb0470481439ed5e3bb59854df82ec9
role:                 0xb0e9b5730d97b99270ce15f439eec98a4f9580e1dfbfb8f5c9e0e3ab71d4bca6
mimeTypeHash:         0xb25570cad408307f58d995c1dadde60bc76e94924d640305a148c9a11f8303bf
filenameHash:         0x31f491635b16d6fb45a7d770fcbcc8cbb6eae32ac98ab622631f4bc4a8c7e9ce
normProfileId:        0xbe97b35c60bb0caee86a5a99022973ef2aa47cbf9586dd34065141c6668b430b
leaf:                 0xa418892b0b93cf88e9d840cf38d36f5bfa16813774f22f5cf02d6b4fcc48375a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;bundle-vector&quot;&gt;Bundle Vector&lt;/h4&gt;

&lt;p&gt;The entries sort in JSON, XML, raw order by their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;role&lt;/code&gt; values. Concatenating
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SCHEMA_V1&lt;/code&gt; with the three leaf values in that order produces:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bundleHash:
0xbe712c4a5eb51d9eb303f1a5c896417a8407a420936fa210626bb66b1a6d0613
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

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

&lt;p&gt;A Solidity reference implementation, hashing library, unit tests, Medusa
property tests, consumer verifier, and independent audit are linked from the
discussion referenced in the preamble. The implementation performs manifest
ordering and hashing over supplied entries; raw JSON and XML normalization
occurs off-chain.&lt;/p&gt;

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

&lt;h3 id=&quot;normalization-profile-trust&quot;&gt;Normalization Profile Trust&lt;/h3&gt;

&lt;p&gt;The determinism guarantee is only as strong as the profile implementation.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROFILE_RAW&lt;/code&gt; performs no normalization. Custom profiles can be ambiguous,
malicious, or incompletely specified. Consumers should verify the selected
profile and reproduce the exact transformation.&lt;/p&gt;

&lt;h3 id=&quot;canonicalization-boundary&quot;&gt;Canonicalization Boundary&lt;/h3&gt;

&lt;p&gt;The Solidity hashing library receives document-entry fields and does not parse
or canonicalize JSON, XML, PDF, images, filenames, or media types. A caller can
submit a hash while falsely claiming that a profile was followed. Consumers
must reproduce normalization and entry derivation off-chain.&lt;/p&gt;

&lt;h3 id=&quot;document-availability-and-privacy&quot;&gt;Document Availability and Privacy&lt;/h3&gt;

&lt;p&gt;An anchored hash does not make its preimage available. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;metadataURI&lt;/code&gt; can become
unavailable, change content, or expose sensitive information. Empty URIs are
permitted. Applications should use durable retrieval policies and must not
place personal, confidential, or legally restricted information directly in a
public URI.&lt;/p&gt;

&lt;h3 id=&quot;declarative-document-count&quot;&gt;Declarative Document Count&lt;/h3&gt;

&lt;p&gt;The anchoring contract cannot verify that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;documentCount&lt;/code&gt; matches the committed
manifest. Consumers should count the reproduced entries rather than trusting
the stored value independently.&lt;/p&gt;

&lt;h3 id=&quot;authorization-and-slot-squatting&quot;&gt;Authorization and Slot Squatting&lt;/h3&gt;

&lt;p&gt;A caller with anchoring authority can occupy an unassigned slot. Implementations
should scope authorization appropriately or pre-assign principals for protected
slots. Recovery administrators can redirect legitimate authority and therefore
require strong operational controls.&lt;/p&gt;

&lt;h3 id=&quot;supersession-front-running&quot;&gt;Supersession Front-Running&lt;/h3&gt;

&lt;p&gt;An administrator attempting direct supersession of a contested slot can be
front-run by the current principal. Implementations supporting recovery should
use atomic principal reassignment before the legitimate principal supersedes the
active bundle.&lt;/p&gt;

&lt;h3 id=&quot;hash-and-encoding-assumptions&quot;&gt;Hash and Encoding Assumptions&lt;/h3&gt;

&lt;p&gt;The construction relies on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; collision resistance. Packed encoding is
used only for fixed-width fields. Implementations must not substitute
variable-length fields into the leaf or bundle encoding without introducing
unambiguous length encoding and a new schema identifier.&lt;/p&gt;

&lt;h3 id=&quot;filename-and-unicode-handling&quot;&gt;Filename and Unicode Handling&lt;/h3&gt;

&lt;p&gt;ASCII case folding does not provide Unicode case equivalence. NFC normalization
requires a conforming Unicode implementation. Different path or Unicode
handling will produce different filename hashes.&lt;/p&gt;

&lt;h3 id=&quot;no-authenticity-or-legal-effect-guarantee&quot;&gt;No Authenticity or Legal-Effect Guarantee&lt;/h3&gt;

&lt;p&gt;A reproducible bundle hash proves agreement on committed bytes, not that a
document is authentic, current, authorized, legally effective, or associated
with the claimed subject.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8326</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8326</guid>
      </item>
      
    
      
      
      <item>
        <title>Directional Transfer Domain Registry</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8327 - Directional Transfer Domain Registry&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8327-directional-transfer-domain-registry/28936&quot;&gt;https://ethereum-magicians.org/t/erc-8327-directional-transfer-domain-registry/28936&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines a token-agnostic registry
interface for querying directional
transfer-route permission between opaque domains by asset class. For an ordered
triple of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, the registry
reports whether that route is currently permitted and exposes the evidence
commitments and effective timestamp associated with its latest state.&lt;/p&gt;

&lt;p&gt;The core interface supports immediate route permission and revocation, state
retrieval, and batch queries. An optional extension supports delayed revocation
with explicit initiation, cancellation, lazy effectiveness, and finalization
semantics.&lt;/p&gt;

&lt;p&gt;This ERC does not assign addresses to domains, derive asset classes, validate
evidence, or enforce token transfers. A token or transfer controller that relies
on a route decision must resolve the applicable domains and asset class, query
the registry, and enforce the result within its transfer path.&lt;/p&gt;

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

&lt;p&gt;Transfer restrictions are commonly expressed in token-local or address-level
logic. That model is appropriate when eligibility depends on a particular
holder, balance, token, or transaction amount. It does not provide a common
lookup surface for policies that apply to transfers between logical domains
across multiple tokens sharing an asset classification.&lt;/p&gt;

&lt;p&gt;A domain can represent a jurisdiction, regulated venue, enterprise network,
game economy, decentralized autonomous organization (DAO) treasury boundary,
or another application-defined context.
Transfer compatibility between such domains is often directional: permission
from domain A to domain B does not imply permission from B to A. The same route
can also differ by asset class.&lt;/p&gt;

&lt;p&gt;Without a shared interface, each token or controller embeds its own route table
or integrates with a proprietary registry. This duplicates policy state and
requires integrations to understand implementation-specific query methods.&lt;/p&gt;

&lt;p&gt;This ERC standardizes the narrow external question:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is the route from this source domain to this destination domain currently
permitted for this asset class?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It deliberately does not answer whether a complete transfer can succeed.
Balances, holder eligibility, freezes, sanctions, settlement conditions, and
token-specific rules remain separate checks.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;domain&lt;/strong&gt; is an opaque, nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; identifier for an
application-defined logical boundary.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;asset class&lt;/strong&gt; is an opaque, nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; identifier for a category of
assets to which one route policy applies.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;route&lt;/strong&gt; is the ordered triple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(sourceDomain, destinationDomain,
assetClass)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;registrar&lt;/strong&gt; is an address authorized by the implementation to modify route
state.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;evidence hash&lt;/strong&gt; is a nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; commitment to application-defined
material supporting a route lifecycle action.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;grace period&lt;/strong&gt; is an implementation-defined delay between initiation and
effectiveness of a graceful revocation.&lt;/p&gt;

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

&lt;p&gt;A compliant registry MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ITransferDomainRegistry&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevoked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isRoutePermitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Route&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permissionEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revokeRoute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isRoutePermittedBatch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClasses&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;permitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;route-direction-and-scope&quot;&gt;Route Direction and Scope&lt;/h3&gt;

&lt;p&gt;Routes MUST be directional. A permitted route &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; MUST NOT imply that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(B, A, C)&lt;/code&gt; is permitted. Bidirectional permission requires two independently
permitted routes.&lt;/p&gt;

&lt;p&gt;Routes MUST also be asset-class scoped. A permitted route &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; MUST NOT
imply permission for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, D)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The registry MUST treat each route triple independently.&lt;/p&gt;

&lt;h3 id=&quot;route-queries&quot;&gt;Route Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; MUST return the current permission state for the exact route
triple. It MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; for a route that has never been permitted, has
been revoked immediately, or has reached the effective time of a graceful
revocation.&lt;/p&gt;

&lt;p&gt;For a given block, the result MUST be deterministic and MUST NOT depend on
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tx.origin&lt;/code&gt;, or caller-specific state.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; MUST return the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Route&lt;/code&gt; representation for the exact triple.
For an unknown route, it MUST return the default record in which every field is
zero.&lt;/p&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; is the time at which the current
permission state became effective. When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; is nonzero, it is the time at which the latest revocation became
effective. An unknown route has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt == 0&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;setting-a-route&quot;&gt;Setting a Route&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject a zero
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteSet&lt;/code&gt; with the stored values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; for an already permitted or previously revoked route is
allowed. The new call replaces the route’s current state and evidence fields;
prior lifecycle actions remain discoverable through events.&lt;/p&gt;

&lt;p&gt;An implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;immediate-revocation&quot;&gt;Immediate Revocation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject a
zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sourceDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;destinationDomain&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt;, or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;preserve the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; with the stored values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For an authorized caller supplying valid nonzero arguments, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST
NOT revert solely because the route was unknown or already revoked. Revoking an
unknown route creates a non-permitted route state with zero permission evidence
and the supplied revocation evidence. Repeated revocation replaces the latest
revocation timestamp and evidence and emits a new event.&lt;/p&gt;

&lt;p&gt;An implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;evidence-semantics&quot;&gt;Evidence Semantics&lt;/h3&gt;

&lt;p&gt;All evidence hashes accepted by this ERC MUST be nonzero. The registry treats
them as opaque commitments and does not validate their preimages, hashing
scheme, authority, correctness, or availability.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt; represents the evidence supplied for the current
permission state. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; represents the evidence supplied for
the current revocation state and MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; while the route is
permitted.&lt;/p&gt;

&lt;p&gt;Route state contains only the latest evidence fields. Consumers reconstructing
the complete lifecycle MUST index the route events.&lt;/p&gt;

&lt;h3 id=&quot;batch-queries&quot;&gt;Batch Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermittedBatch&lt;/code&gt; MUST revert when its three arrays have different
lengths. Otherwise, it MUST return an array of the same length in which output
element &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt; equals:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;isRoutePermitted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;sourceDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;destinationDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;assetClasses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Implementations MAY impose a documented maximum batch size. Consumers calling
the batch function from state-changing execution SHOULD bound the input length.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-extension&quot;&gt;Graceful Revocation Extension&lt;/h3&gt;

&lt;p&gt;Graceful revocation is OPTIONAL. A registry implementing it MUST implement both
the core interface and the following extension:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IGracefulRouteRevocation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
   &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Revocation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevocationInitiated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiatedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveAt&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RouteRevocationCancelled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancellationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Revocation&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiateRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revocationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancelRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancellationEvidenceHash&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

   &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finalizeRevocation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
       &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The grace-period duration and its configuration mechanism are implementation
defined. The implementation MUST document that policy. Only the resulting
timestamps and state transitions are standardized.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-initiation&quot;&gt;Graceful Revocation Initiation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateRevocation&lt;/code&gt; MUST be restricted to authorized registrars. It MUST
reject a zero route identifier or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It MUST revert unless &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; currently returns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the route
and no graceful revocation is pending.&lt;/p&gt;

&lt;p&gt;On success, it MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiatedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to a representable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt; value strictly later than
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiatedAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;store the supplied &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalized&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationInitiated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The route MUST remain permitted while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;lt; effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;lazy-effectiveness&quot;&gt;Lazy Effectiveness&lt;/h3&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt;= effectiveAt&lt;/code&gt; for a pending graceful revocation,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; without requiring a finalization
transaction.&lt;/p&gt;

&lt;p&gt;During that interval, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; MUST return an effective route representation
with:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permitted == false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; equal to the graceful revocation’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;the existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;permissionEvidenceHash&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; equal to the graceful revocation evidence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The stored revocation remains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; until finalized, but the route is
already non-permitted. Therefore, consumers MUST NOT infer route permission
from whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; has been emitted.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-cancellation&quot;&gt;Graceful Revocation Cancellation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancelRevocation&lt;/code&gt; MUST be restricted to authorized registrars. It MUST reject
a zero route identifier or zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancellationEvidenceHash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It MUST revert unless a revocation is pending and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;lt; effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, it MUST clear the revocation state and emit
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationCancelled&lt;/code&gt;. The route remains permitted. The cancellation
evidence is emitted but is not retained in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Revocation&lt;/code&gt; struct; consumers
requiring it MUST index the event.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-finalization&quot;&gt;Graceful Revocation Finalization&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalizeRevocation&lt;/code&gt; MUST reject a zero route identifier. It MUST revert unless
a revocation is pending and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp &amp;gt;= effectiveAt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On success, it MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;finalized&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;persist the route as non-permitted;&lt;/li&gt;
  &lt;li&gt;set the route’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; to the graceful revocation effective time;&lt;/li&gt;
  &lt;li&gt;store the graceful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revocationEvidenceHash&lt;/code&gt; on the route; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; exactly once for that graceful revocation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finalization MAY be permissionless because route effectiveness does not depend
on it. Repeated or nonexistent finalization MUST NOT emit a duplicate
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;The finalized &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Revocation&lt;/code&gt; record MUST remain queryable until another route
lifecycle action clears it.&lt;/p&gt;

&lt;h3 id=&quot;interaction-with-core-lifecycle-functions&quot;&gt;Interaction With Core Lifecycle Functions&lt;/h3&gt;

&lt;p&gt;In a registry implementing the graceful extension, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; MUST clear any
pending or finalized graceful-revocation record before installing the new
permission state.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt; MUST clear any pending or finalized graceful-revocation record
before installing the immediate revocation state.&lt;/p&gt;

&lt;p&gt;These actions do not emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevocationCancelled&lt;/code&gt;. Their respective
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteSet&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; event records the state transition.&lt;/p&gt;

&lt;h3 id=&quot;domain-and-asset-class-identification&quot;&gt;Domain and Asset-Class Identification&lt;/h3&gt;

&lt;p&gt;This ERC does not map accounts or tokens to domains and does not define domain
or asset-class taxonomies. Applications MUST document how they derive each
identifier supplied to the registry.&lt;/p&gt;

&lt;p&gt;Identifiers SHOULD be domain separated by an application or registry
namespace. The same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt; value in two independent registries MUST NOT be
assumed to have the same meaning without an explicit coordination agreement.&lt;/p&gt;

&lt;p&gt;An asset class MAY represent a regulatory category, asset type, product class,
or a single asset when per-asset routing is required. The mapping from an
individual token or asset identifier to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assetClass&lt;/code&gt; is application defined.&lt;/p&gt;

&lt;h3 id=&quot;authorization&quot;&gt;Authorization&lt;/h3&gt;

&lt;p&gt;Registrar authorization is implementation defined. A registry MAY use
ownership, role-based access control, governance, signatures, or another
documented mechanism.&lt;/p&gt;

&lt;p&gt;Whatever mechanism is selected, unauthorized callers MUST NOT be able to call
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateRevocation&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancelRevocation&lt;/code&gt;
successfully.&lt;/p&gt;

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

&lt;p&gt;Compliant registries MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(ITransferDomainRegistry).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Registries implementing graceful revocation MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IGracefulRouteRevocation).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not prove that route data is
correct, that the registry is governed appropriately, or that a token or
controller enforces registry decisions.&lt;/p&gt;

&lt;h3 id=&quot;consumer-enforcement&quot;&gt;Consumer Enforcement&lt;/h3&gt;

&lt;p&gt;A consumer enforcing a route decision SHOULD perform the following within the
same transaction as the governed transfer:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Resolve the sender and receiver to the applicable source and destination
  domains using an authoritative application-defined mechanism.&lt;/li&gt;
  &lt;li&gt;Resolve the token or asset to the applicable asset class.&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted(sourceDomain, destinationDomain, assetClass)&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Reject the transfer when the result is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Apply all independent token, identity, balance, freeze, sanctions, and
  settlement checks required by the application.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Checking route permission off-chain before submitting a later transfer does not
provide atomic enforcement because route state can change between the check and
execution.&lt;/p&gt;

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

&lt;h3 id=&quot;why-directional-routes&quot;&gt;Why Directional Routes?&lt;/h3&gt;

&lt;p&gt;Compatibility can be asymmetric. A domain may allow outbound transfers to
another domain without accepting inbound transfers from it. Encoding each
direction separately avoids an unsafe assumption of reciprocity.&lt;/p&gt;

&lt;h3 id=&quot;why-opaque-domains&quot;&gt;Why Opaque Domains?&lt;/h3&gt;

&lt;p&gt;Standardizing one universal domain taxonomy would couple the interface to a
particular legal, organizational, or application model. Opaque identifiers let
independent systems use the same route interface while defining their own
meaning and resolution mechanism.&lt;/p&gt;

&lt;h3 id=&quot;why-scope-routes-by-asset-class&quot;&gt;Why Scope Routes by Asset Class?&lt;/h3&gt;

&lt;p&gt;The same pair of domains can permit one category of assets and prohibit
another. Asset-class scoping allows multiple assets governed by the same route
policy to share one entry without requiring per-token route storage.&lt;/p&gt;

&lt;h3 id=&quot;why-an-external-registry&quot;&gt;Why an External Registry?&lt;/h3&gt;

&lt;p&gt;An external registry allows multiple tokens and controllers to consult one
route-policy surface. It also separates route administration from token
implementation and avoids requiring every supported token standard to adopt
the same storage model.&lt;/p&gt;

&lt;h3 id=&quot;why-isroutepermitted-instead-of-cantransfer&quot;&gt;Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isRoutePermitted&lt;/code&gt; Instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canTransfer&lt;/code&gt;?&lt;/h3&gt;

&lt;p&gt;The registry evaluates only the supplied route triple. A name such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canTransfer&lt;/code&gt; would imply checks that the interface does not perform, including
balances, account eligibility, freezes, sanctions, and token-specific rules.&lt;/p&gt;

&lt;h3 id=&quot;why-require-nonzero-evidence-commitments&quot;&gt;Why Require Nonzero Evidence Commitments?&lt;/h3&gt;

&lt;p&gt;A zero hash is ambiguous between absent evidence and a meaningful commitment.
Requiring a nonzero value makes absence explicit at the application layer and
prevents route records from silently appearing documented when no commitment
was supplied.&lt;/p&gt;

&lt;h3 id=&quot;why-is-immediate-revocation-idempotent-over-route-existence&quot;&gt;Why Is Immediate Revocation Idempotent Over Route Existence?&lt;/h3&gt;

&lt;p&gt;An authorized registrar should be able to establish a route as non-permitted
without first proving that it was previously enabled. This supports defensive
revocation and repeated emergency actions while retaining each action in the
event history.&lt;/p&gt;

&lt;h3 id=&quot;why-graceful-revocation-as-an-extension&quot;&gt;Why Graceful Revocation as an Extension?&lt;/h3&gt;

&lt;p&gt;Some systems need immediate emergency closure. Others have in-flight settlement
or notice obligations that require a future effective time. Keeping delayed
revocation optional preserves a small core interface while standardizing the
additional lifecycle only for deployments that need it.&lt;/p&gt;

&lt;h3 id=&quot;why-lazy-effectiveness&quot;&gt;Why Lazy Effectiveness?&lt;/h3&gt;

&lt;p&gt;If route closure depended on a later finalization transaction, a missing or
censored transaction could leave the route permitted indefinitely. Lazy
effectiveness makes the announced timestamp authoritative. Finalization exists
to persist state and emit the terminal event, not to activate the revocation.&lt;/p&gt;

&lt;h3 id=&quot;why-keep-grace-period-configuration-implementation-defined&quot;&gt;Why Keep Grace-Period Configuration Implementation Defined?&lt;/h3&gt;

&lt;p&gt;Appropriate delay depends on the applicable settlement cycle and policy. The
interface exposes the resulting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt; timestamp, which consumers need
for interoperability, without prescribing one configuration mechanism or
duration.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;./eip-3643.md&quot;&gt;ERC-3643&lt;/a&gt; defines a regulated-token architecture with identity
registries, compliance modules, and token lifecycle functions. This ERC does
not define holder eligibility or token behavior; it provides one route-policy
input that such systems may optionally consume.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-7943.md&quot;&gt;ERC-7943&lt;/a&gt; defines a universal real-world asset (RWA) token
interface including transfer eligibility, freezing, and forced transfer
behavior. This ERC is an external registry keyed by domains and asset classes
rather than a token behavior interface.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token
standards. Existing &lt;a href=&quot;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt;, &lt;a href=&quot;./eip-721.md&quot;&gt;ERC-721&lt;/a&gt;,
&lt;a href=&quot;./eip-1155.md&quot;&gt;ERC-1155&lt;/a&gt;, &lt;a href=&quot;./eip-3643.md&quot;&gt;ERC-3643&lt;/a&gt;,
&lt;a href=&quot;./eip-7943.md&quot;&gt;ERC-7943&lt;/a&gt;, and custom tokens remain unaffected unless their
transfer path is explicitly integrated with a registry.&lt;/p&gt;

&lt;p&gt;The registry does not require a token to expose a new interface. A token,
compliance module, transfer controller, bridge, or settlement contract can call
the registry as an external dependency.&lt;/p&gt;

&lt;p&gt;Implementations that do not need delayed revocation implement only
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ITransferDomainRegistry&lt;/code&gt;. Implementations that need delayed revocation
additionally implement &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IGracefulRouteRevocation&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;directional independence of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A, B, C)&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(B, A, C)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;asset-class independence for the same domain pair;&lt;/li&gt;
  &lt;li&gt;caller-independent route queries;&lt;/li&gt;
  &lt;li&gt;default false and zero state for unknown routes;&lt;/li&gt;
  &lt;li&gt;nonzero validation for route identifiers and every evidence field;&lt;/li&gt;
  &lt;li&gt;setting, repeated setting, immediate revocation, repeated revocation, and
 re-enablement;&lt;/li&gt;
  &lt;li&gt;immediate revocation of an unknown route;&lt;/li&gt;
  &lt;li&gt;route evidence retrieval and event history;&lt;/li&gt;
  &lt;li&gt;batch output equivalence with individual queries;&lt;/li&gt;
  &lt;li&gt;mismatched batch lengths and implementation batch limits;&lt;/li&gt;
  &lt;li&gt;graceful initiation only for a currently permitted route;&lt;/li&gt;
  &lt;li&gt;permission before, and non-permission at, graceful &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;lazy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRoute&lt;/code&gt; behavior before finalization;&lt;/li&gt;
  &lt;li&gt;cancellation before expiry and rejection at or after expiry;&lt;/li&gt;
  &lt;li&gt;finalization persistence and duplicate-event prevention;&lt;/li&gt;
  &lt;li&gt;immediate revocation and re-enablement while graceful state exists;&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection; and&lt;/li&gt;
  &lt;li&gt;unauthorized lifecycle calls.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A Solidity reference implementation includes immediate and graceful registry
contracts, a canonical route-key library, unit and fuzz tests, Medusa property
tests, deployment scripts, and an independent audit. These materials are linked
from the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation uses role-based registrar authorization, a
deployment-time fixed grace period, a maximum batch size of 256, and:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
   &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sourceDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;destinationDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;as its internal route key. Those storage and administration choices are not
required for conforming implementations.&lt;/p&gt;

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

&lt;h3 id=&quot;no-enforcement-guarantee&quot;&gt;No Enforcement Guarantee&lt;/h3&gt;

&lt;p&gt;The registry is advisory. A token or controller that does not query and enforce
the result can transfer regardless of route state. ERC-165 support by either
contract does not prove that enforcement occurs.&lt;/p&gt;

&lt;h3 id=&quot;domain-and-asset-class-resolution&quot;&gt;Domain and Asset-Class Resolution&lt;/h3&gt;

&lt;p&gt;The registry evaluates caller-supplied identifiers. Incorrect, stale, or
malicious resolution of an address or token to a domain or asset class can
bypass the intended policy even when the registry itself is correct. Consumers
must secure and document their resolution mechanism.&lt;/p&gt;

&lt;h3 id=&quot;registry-and-registrar-trust&quot;&gt;Registry and Registrar Trust&lt;/h3&gt;

&lt;p&gt;A malicious or compromised registrar can permit prohibited routes, revoke
valid routes, replace evidence commitments, or repeatedly change state. Users
must evaluate the registry’s authorization, governance, upgrade, and key
management policies.&lt;/p&gt;

&lt;h3 id=&quot;evidence-limitations&quot;&gt;Evidence Limitations&lt;/h3&gt;

&lt;p&gt;An evidence hash proves only commitment to unknown bytes if the preimage is
available. It does not establish authenticity, legal effect, correctness,
authority, or continued availability. Consumers relying on evidence must obtain
and verify the preimage under an agreed hashing and document scheme.&lt;/p&gt;

&lt;h3 id=&quot;transaction-atomicity-and-races&quot;&gt;Transaction Atomicity and Races&lt;/h3&gt;

&lt;p&gt;An off-chain route query can become stale before a transfer executes. Enforcing
consumers should query the registry and complete or reject the transfer within
the same transaction.&lt;/p&gt;

&lt;h3 id=&quot;graceful-revocation-risk&quot;&gt;Graceful Revocation Risk&lt;/h3&gt;

&lt;p&gt;The route remains permitted before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;, so the grace period creates a
known window in which transfers can continue. Applications must choose a delay
appropriate to their threat and settlement models. Emergency closure should
use immediate revocation.&lt;/p&gt;

&lt;p&gt;An authorized registrar can clear graceful state by calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setRoute&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revokeRoute&lt;/code&gt;. Consumers requiring governance constraints around reinstatement
must enforce them in the registry’s authorization policy.&lt;/p&gt;

&lt;h3 id=&quot;lazy-revocation-and-event-only-indexers&quot;&gt;Lazy Revocation and Event-Only Indexers&lt;/h3&gt;

&lt;p&gt;A graceful revocation becomes effective without a transaction at
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveAt&lt;/code&gt;. An indexer that waits only for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RouteRevoked&lt;/code&gt; can report stale
permission until finalization. Consumers must evaluate timestamps or call the
view interface.&lt;/p&gt;

&lt;h3 id=&quot;batch-gas-consumption&quot;&gt;Batch Gas Consumption&lt;/h3&gt;

&lt;p&gt;Although batch lookup is a view function, another contract can invoke it from a
state-changing transaction. Unbounded arrays can consume excessive gas or make
the calling operation unavailable. Implementations and callers should apply
appropriate limits.&lt;/p&gt;

&lt;h3 id=&quot;identifier-collisions-and-cross-registry-meaning&quot;&gt;Identifier Collisions and Cross-Registry Meaning&lt;/h3&gt;

&lt;p&gt;Opaque identifiers have no global namespace. Two applications or registries
can assign the same value to different domains or asset classes. Consumers must
scope interpretation to the selected registry and its documented namespace.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Graceful revocation depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. Block producers can influence
timestamps within protocol bounds. Applications requiring exact wall-clock
cutoffs must account for this uncertainty.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8327</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8327</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked Compliance Event Log</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8328 - Subject-Linked Compliance Event Log&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8328-subject-linked-compliance-event-log/28937&quot;&gt;https://ethereum-magicians.org/t/erc-8328-subject-linked-compliance-event-log/28937&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an append-only interface for
subject-linked compliance event
records. Each record includes a subject, event type, outcome, technical actor,
claimed authority, involved parties, evidence commitment, optional evidence
location, versioned payload profile, operation reference, occurrence time, and
recording time.&lt;/p&gt;

&lt;p&gt;Events are indexed per subject and by event type. Corrections are recorded as
new events linked to earlier records. A forward pointer on the corrected record
prevents correction forks and allows consumers to resolve the terminal event in
a correction chain.&lt;/p&gt;

&lt;p&gt;This ERC is a reporting interface. It does not define compliance policy,
identity verification, transfer restrictions, legal authority, or regulatory
compliance. Stored records are attributable assertions, not proof that the
reported action occurred or was lawful.&lt;/p&gt;

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

&lt;p&gt;Compliance-relevant lifecycle actions are currently represented through
application-specific events, token-local state changes, generic attestations,
and off-chain databases. This fragmentation makes it difficult for contracts,
indexers, auditors, and reporting systems to query comparable records across
implementations.&lt;/p&gt;

&lt;p&gt;Existing token and compliance standards primarily define token behavior,
holder eligibility, transfer validation, or entity classification. Those
capabilities do not provide a common stored record for subject-level lifecycle
actions such as issuance, redemption, freezing, know-your-customer (KYC)
status changes, regulatory holds, policy changes, and forced transfers.&lt;/p&gt;

&lt;p&gt;A shared event-log interface provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;one query surface for records attached to an application-defined subject;&lt;/li&gt;
  &lt;li&gt;explicit separation between the recorder and the claimed authority;&lt;/li&gt;
  &lt;li&gt;structured party roles rather than untyped address arrays;&lt;/li&gt;
  &lt;li&gt;evidence commitments and optional retrieval references;&lt;/li&gt;
  &lt;li&gt;versioned payload profiles for interoperable event-specific data;&lt;/li&gt;
  &lt;li&gt;per-type indexing without scanning an entire subject history; and&lt;/li&gt;
  &lt;li&gt;append-only, fork-free correction provenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The log can be called by a token, compliance module, governance executor,
multisig, or other authorized recorder. It does not require any particular
token standard or enforcement architecture.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;subject&lt;/strong&gt; is an application-defined entity identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; and,
optionally, contextualized by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;compliance event&lt;/strong&gt; is a stored assertion about a compliance-relevant action
or state transition concerning a subject.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;actor&lt;/strong&gt; is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; at the time &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; is called. It identifies
the technical recorder, not necessarily the human decision-maker or legal
authority.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;authority&lt;/strong&gt; is the recorder’s claimed legal, regulatory, contractual, or
governance basis for the event. The claim is not verified by the log.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;party&lt;/strong&gt; is an EVM address associated with an explicit role in the event.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;payload profile&lt;/strong&gt; is a versioned schema declaring how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; is encoded.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;correction chain&lt;/strong&gt; is a linear sequence of events linked by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal event&lt;/strong&gt; is an event whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-values&quot;&gt;Sentinel Values&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTED_BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; indicates that an event does not correct an earlier event.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; indicates that an event has no successor correction. Event
index zero is safe for this sentinel because a correction’s index is always
greater than the index it corrects and therefore can never be zero.&lt;/p&gt;

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

&lt;p&gt;A compliant log MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IComplianceEventLog&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;role&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComplianceEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ComplianceEventRecorded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;actor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outcome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authority&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Party&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parties&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payloadProfileId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;payload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;occurredAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ComplianceEvent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentEventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isEventCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventCountByType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventByTypeAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastRecordedEventByType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventType&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;recording-semantics&quot;&gt;Recording Semantics&lt;/h3&gt;

&lt;p&gt;Event indices MUST be zero-based and scoped per &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. The returned
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex&lt;/code&gt; MUST equal the subject’s event count immediately before the new
event is appended.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST be restricted to authorized recorders. The authorization
mechanism is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted event, the implementation MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store every supplied field without changing its value, except as explicitly
specified by this ERC;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;actor&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;append the event index to the subject and event-type index;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ComplianceEventRecorded&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;return the new event index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementation MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be
represented as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceURI&lt;/code&gt; MAY be empty when the
evidence location is private, unavailable on-chain, or exchanged out of band.
An empty URI does not weaken the requirement for a nonzero commitment.&lt;/p&gt;

&lt;p&gt;The parties array MUST contain no more than 10 entries. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payload&lt;/code&gt; MUST contain
no more than 2048 bytes. Empty party arrays and empty payloads are allowed.&lt;/p&gt;

&lt;p&gt;This ERC does not require nonzero values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventType&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outcome&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authority&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operationRef&lt;/code&gt;, party addresses, party
roles, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt;. Applications requiring stricter semantics MUST
enforce and document them before calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;temporal-semantics&quot;&gt;Temporal Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; represents when the reported action occurred. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordedAt&lt;/code&gt;
represents when the record was appended on-chain.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt &amp;gt; block.timestamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations SHOULD impose and document a maximum backdating interval.
Different deployments can require different intervals, so the duration is not
standardized by this ERC.&lt;/p&gt;

&lt;p&gt;The log does not independently verify &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt;. It is an assertion by the
recorder.&lt;/p&gt;

&lt;h3 id=&quot;append-only-semantics&quot;&gt;Append-Only Semantics&lt;/h3&gt;

&lt;p&gt;Once recorded, every event field MUST remain immutable except
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;. Events MUST NOT be deleted.&lt;/p&gt;

&lt;p&gt;Updating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; is permitted only when accepting a valid correction
under the correction rules below.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original or non-correction event MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; and MUST NOT use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;, which is defined in the Event Types section below:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;correctsIndex = NO_CORRECTION
eventType != EVT_CORRECTION
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A correction event MUST use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;correctsIndex = index of the corrected event
eventType = EVT_CORRECTION
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For a correction, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; to identify an earlier event under the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;require the target event’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to equal
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;authorize the correction under the implementation’s documented correction
policy;&lt;/li&gt;
  &lt;li&gt;set the target’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to the new correction event index; and&lt;/li&gt;
  &lt;li&gt;append the correction as a new event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The correction policy MUST NOT permit an ordinary recorder to correct another
actor’s event merely because both addresses can record events. It MAY authorize
the original actor, a designated corrector, or an administrator. The policy
MUST be documented.&lt;/p&gt;

&lt;p&gt;Each event can be corrected at most once, preventing forks. A correction event
can itself be corrected later, producing a linear chain.&lt;/p&gt;

&lt;p&gt;The correcting record does not rewrite the original event’s event type or
payload. Recorders MUST place the corrected assertion in the new event’s fields
or an application-defined correction payload. Consumers MUST interpret the
terminal event under the applicable profile and application policy.&lt;/p&gt;

&lt;h3 id=&quot;current-state-queries&quot;&gt;Current-State Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt;.
Otherwise, it MUST follow &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; until reaching
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; and return the terminal event index. Calling it on a terminal
event MUST return the supplied index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isEventCurrent&lt;/code&gt; MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt; and
otherwise return whether &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex == NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because corrections always point to earlier events and each event has at most
one successor, conforming correction chains cannot contain cycles or branches.&lt;/p&gt;

&lt;h3 id=&quot;event-retrieval-and-counting&quot;&gt;Event Retrieval and Counting&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getEvent&lt;/code&gt; MUST return the complete stored event and MUST revert when
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventIndex &amp;gt;= eventCount(subjectId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventCount&lt;/code&gt; MUST return the number of events stored under a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventCountByType&lt;/code&gt; MUST return the number of events recorded with the exact
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventType&lt;/code&gt; under a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eventByTypeAt&lt;/code&gt; MUST return the event index at the specified zero-based ordinal
and MUST revert when the ordinal is outside the type-specific index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt; MUST return the greatest event index recorded with
the exact event type and MUST revert when no matching event exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt; describes recording order. It does not select the
event with the greatest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; and does not resolve correction chains.&lt;/p&gt;

&lt;p&gt;Correction events are indexed under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;, not under the event type
they correct. Consumers resolving an earlier event MUST use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; rather than assuming the last event of the original type is
its current state.&lt;/p&gt;

&lt;h3 id=&quot;subject-identifiers&quot;&gt;Subject Identifiers&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectType&lt;/code&gt; are opaque to the log. Applications SHOULD use a
documented, domain-separated derivation and MUST NOT assume that equal subject
identifiers from independent logs have equal meaning without an explicit
coordination agreement.&lt;/p&gt;

&lt;p&gt;The following subject-type identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_TOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_ADDRESS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:ADDRESS&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_ASSET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:ASSET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SUBJECT_CASE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:SUBJECT_TYPE:CASE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MAY define custom subject types using a documented namespace and
version.&lt;/p&gt;

&lt;h3 id=&quot;event-types&quot;&gt;Event Types&lt;/h3&gt;

&lt;p&gt;The following event-type identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ISSUANCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ISSUANCE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_TRANSFER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_REDEMPTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:REDEMPTION:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_FREEZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:FREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_UNFREEZE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:UNFREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_FORCED_TRANSFER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:FORCED_TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_APPROVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_APPROVED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_REVOKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_REVOKED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_KYC_UPDATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:KYC_UPDATED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_REGULATORY_HOLD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:REGULATORY_HOLD:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_HOLD_RELEASED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:HOLD_RELEASED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ALLOWLIST_ADDED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ALLOWLIST_ADDED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_ALLOWLIST_REMOVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:ALLOWLIST_REMOVED:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_POLICY_CHANGE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:POLICY_CHANGE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EVT_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:EVENT_TYPE:CORRECTION:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_TRANSFER&lt;/code&gt; is intended for compliance-significant transfer records, not as
a replacement for a token’s ordinary transfer event. Applications SHOULD avoid
duplicating every routine token transfer unless the additional compliance
record is required by their reporting policy.&lt;/p&gt;

&lt;p&gt;Custom event types SHOULD use a domain-separated namespace and explicit
version.&lt;/p&gt;

&lt;h3 id=&quot;party-roles&quot;&gt;Party Roles&lt;/h3&gt;

&lt;p&gt;The following party-role identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_SENDER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:SENDER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_RECEIVER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:RECEIVER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_TARGET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:TARGET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_BENEFICIARY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:BENEFICIARY&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_CONTROLLER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:CONTROLLER&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ROLE_SUBJECT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PARTY_ROLE:SUBJECT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom party roles SHOULD use a documented namespace and version.&lt;/p&gt;

&lt;p&gt;The base &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Party&lt;/code&gt; type contains an EVM address. It cannot carry an arbitrary
hashed identity without changing the interface. Applications needing private
or non-address party identifiers require a separate extension or SHOULD omit
those parties from the public record.&lt;/p&gt;

&lt;h3 id=&quot;outcomes&quot;&gt;Outcomes&lt;/h3&gt;

&lt;p&gt;The following outcome identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_APPROVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:APPROVED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_DENIED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:DENIED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_PENDING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:PENDING&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_EXECUTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:EXECUTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_EXPIRED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:EXPIRED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTCOME_REVOKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:OUTCOME:REVOKED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This ERC does not define or enforce an event-type and outcome compatibility
matrix. Applications MAY constrain combinations before recording. Consumers
MUST NOT infer that a combination was validated merely because the log accepted
it.&lt;/p&gt;

&lt;h3 id=&quot;authority-identifiers&quot;&gt;Authority Identifiers&lt;/h3&gt;

&lt;p&gt;The following common authority identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_INTERNAL_POLICY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:INTERNAL_POLICY:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_COURT_ORDER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:COURT_ORDER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AUTHORITY_REGULATOR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:AUTHORITY:REGULATOR:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom authority identifiers SHOULD use a documented namespace and version.
The field records a claim and does not authenticate the named authority.&lt;/p&gt;

&lt;h3 id=&quot;payload-profiles&quot;&gt;Payload Profiles&lt;/h3&gt;

&lt;p&gt;The following payload-profile identifiers and ABI encodings are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_TRANSFER_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address from,
//     address to,
//     uint256 amount,
//     bytes32 routeRef
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_FREEZE_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:FREEZE:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address target,
//     uint256 amount,
//     uint64 expiresAt,
//     bytes32 reason
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_KYC_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:KYC:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address subject,
//     bytes32 jurisdiction,
//     bytes32 riskTier,
//     uint64 expiresAt
// )
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PAYLOAD_FORCED_TRANSFER_V1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8328:PAYLOAD:FORCED_TRANSFER:V1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// abi.encode(
//     address from,
//     address to,
//     uint256 amount,
//     bytes32 legalBasis
// )
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A recorder declaring one of these profiles MUST encode the payload exactly as
specified. Consumers MUST inspect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt; before decoding.&lt;/p&gt;

&lt;p&gt;The log is not required to decode payloads or validate compatibility between a
payload profile, event type, parties, and outcome. Consumers SHOULD reject a
malformed known profile. Unknown profile identifiers MUST be treated as opaque
bytes.&lt;/p&gt;

&lt;p&gt;Custom payload profiles SHOULD use a documented namespace and version and MUST
define an exact encoding.&lt;/p&gt;

&lt;h3 id=&quot;operation-references&quot;&gt;Operation References&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operationRef&lt;/code&gt; is an application-defined correlation identifier linking the
record to an underlying action or workflow. It MAY be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; when no such
reference is available.&lt;/p&gt;

&lt;p&gt;A contract cannot access its transaction hash or final log index while
executing. Therefore, this ERC does not require a transaction-hash and log-index
derivation. Applications SHOULD compute a correlation identifier before the
underlying action and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordEvent&lt;/code&gt; calls when both occur in one transaction.&lt;/p&gt;

&lt;p&gt;Recording an event in the same transaction as the underlying action provides
stronger linkage than recording it later, but the log still does not prove that
the record accurately describes that action.&lt;/p&gt;

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

&lt;p&gt;Compliant logs MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IComplianceEventLog).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish recorder
trustworthiness, evidence validity, authority, policy correctness, or legal
compliance.&lt;/p&gt;

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

&lt;h3 id=&quot;why-subject-linked-records&quot;&gt;Why Subject-Linked Records?&lt;/h3&gt;

&lt;p&gt;An address-only or token-only key would exclude projects, assets, cases,
policies, and application-defined entities. An opaque subject identifier allows
one query model while leaving identity and namespace semantics to the
application.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-actor-and-authority&quot;&gt;Why Separate Actor and Authority?&lt;/h3&gt;

&lt;p&gt;The technical account recording an event and the claimed basis for the action
are different facts. A module can execute several actions under different
mandates, while multiple modules can act under the same mandate.&lt;/p&gt;

&lt;h3 id=&quot;why-structured-parties&quot;&gt;Why Structured Parties?&lt;/h3&gt;

&lt;p&gt;An untyped address list cannot distinguish a sender, receiver, target,
beneficiary, or controller. Explicit roles improve machine interpretation while
keeping the set extensible.&lt;/p&gt;

&lt;h3 id=&quot;why-require-an-evidence-commitment-but-permit-an-empty-uri&quot;&gt;Why Require an Evidence Commitment but Permit an Empty URI?&lt;/h3&gt;

&lt;p&gt;Every record should commit to the evidence representation used by the recorder,
but public retrieval can be inappropriate for confidential or regulated data.
A nonzero hash preserves the commitment while an optional URI permits private
distribution.&lt;/p&gt;

&lt;h3 id=&quot;why-versioned-payload-profiles&quot;&gt;Why Versioned Payload Profiles?&lt;/h3&gt;

&lt;p&gt;Opaque bytes without a declared schema prevent interoperable decoding.
Versioned profile identifiers let consumers recognize stable base encodings and
safely preserve unknown custom payloads.&lt;/p&gt;

&lt;h3 id=&quot;why-correction-events-instead-of-mutable-records&quot;&gt;Why Correction Events Instead of Mutable Records?&lt;/h3&gt;

&lt;p&gt;Replacing an event would erase the prior assertion. A correction chain retains
the full history and identifies the current terminal record. The forward
pointer and single-successor rule prevent competing corrections to the same
event.&lt;/p&gt;

&lt;h3 id=&quot;why-index-corrections-under-their-own-type&quot;&gt;Why Index Corrections Under Their Own Type?&lt;/h3&gt;

&lt;p&gt;A correction is a distinct lifecycle action. Indexing it under
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt; preserves the original event-type history and lets consumers
query correction activity directly. Chain-resolution helpers provide current
state when needed.&lt;/p&gt;

&lt;h3 id=&quot;why-store-records-rather-than-emit-events-only&quot;&gt;Why Store Records Rather Than Emit Events Only?&lt;/h3&gt;

&lt;p&gt;EVM contracts cannot read historical logs. Storing records allows on-chain
consumers to retrieve event details, traverse correction chains, and iterate by
event type. Emitted events remain useful for off-chain indexing.&lt;/p&gt;

&lt;h3 id=&quot;why-keep-policy-validation-outside-the-log&quot;&gt;Why Keep Policy Validation Outside the Log?&lt;/h3&gt;

&lt;p&gt;The same event and outcome identifiers can be used under different legal and
application policies. The log standardizes representation and provenance, not
the rule engine deciding which combinations are valid.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;./eip-20.md&quot;&gt;ERC-20&lt;/a&gt; defines fungible-token transfers and balance changes.
This ERC records subject-linked lifecycle assertions and does not require each
record to correspond to an ERC-20 balance change.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-3643.md&quot;&gt;ERC-3643&lt;/a&gt; defines regulated-token behavior, identity
registries, compliance modules, and lifecycle operations. This ERC is a
reporting layer that such a system may call; it does not replace enforcement or
identity checks.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-7943.md&quot;&gt;ERC-7943&lt;/a&gt; defines real-world asset (RWA) token behavior
including transfer eligibility, freezing, and forced transfers. This ERC
records attributed lifecycle assertions independently of any token interface.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces a new interface and does not modify existing token,
identity, attestation, or compliance standards.&lt;/p&gt;

&lt;p&gt;An existing token or compliance module can call a companion
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IComplianceEventLog&lt;/code&gt; without changing its base token interface. Systems that do
not integrate with the log are unaffected.&lt;/p&gt;

&lt;p&gt;The subject identifier is application defined, so adoption does not require a
particular asset registry or token standard.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zero-based, per-subject event indexing;&lt;/li&gt;
  &lt;li&gt;subject isolation and event-type indexing;&lt;/li&gt;
  &lt;li&gt;actor assignment to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;recording-time assignment and future-event rejection;&lt;/li&gt;
  &lt;li&gt;the configured backdating policy;&lt;/li&gt;
  &lt;li&gt;rejection of zero evidence commitments;&lt;/li&gt;
  &lt;li&gt;empty and non-empty evidence URIs;&lt;/li&gt;
  &lt;li&gt;party and payload size boundaries;&lt;/li&gt;
  &lt;li&gt;original-event and correction-event guards;&lt;/li&gt;
  &lt;li&gt;correction target bounds and same-subject behavior;&lt;/li&gt;
  &lt;li&gt;original-actor, administrator, and unauthorized correction paths;&lt;/li&gt;
  &lt;li&gt;correction fork prevention and multi-step linear chains;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; from original, intermediate, and terminal events;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isEventCurrent&lt;/code&gt; for corrected and terminal events;&lt;/li&gt;
  &lt;li&gt;invalid event and ordinal queries;&lt;/li&gt;
  &lt;li&gt;recording-order behavior of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lastRecordedEventByType&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;correction indexing under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EVT_CORRECTION&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;exact base payload-profile encodings;&lt;/li&gt;
  &lt;li&gt;opaque handling of unknown payload profiles;&lt;/li&gt;
  &lt;li&gt;acceptance of unconstrained event-type and outcome combinations; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A Solidity reference implementation, constants library, unit tests, Medusa
property tests, and independent audit are linked from the official discussion
thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses recorder and administrator roles;&lt;/li&gt;
  &lt;li&gt;permits the original actor or an administrator with recorder authority to
correct an event;&lt;/li&gt;
  &lt;li&gt;limits party arrays to 10 entries;&lt;/li&gt;
  &lt;li&gt;limits payloads to 2048 bytes;&lt;/li&gt;
  &lt;li&gt;rejects events backdated by more than 30 days;&lt;/li&gt;
  &lt;li&gt;stores unknown payload profiles without decoding them; and&lt;/li&gt;
  &lt;li&gt;does not validate event-type and outcome combinations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role design and the 30-day backdating window are reference deployment choices.
The size limits and externally observable interface behavior are requirements
of this ERC.&lt;/p&gt;

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

&lt;h3 id=&quot;recorder-trust&quot;&gt;Recorder Trust&lt;/h3&gt;

&lt;p&gt;The log proves that an authorized address recorded particular bytes. It does
not prove that the record is true. A compromised, malicious, or incorrectly
authorized recorder can submit false or misleading events.&lt;/p&gt;

&lt;h3 id=&quot;claimed-authority&quot;&gt;Claimed Authority&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authority&lt;/code&gt; is self-asserted. A recorder can claim a court order, regulator, or
internal policy that does not exist or does not authorize the action. Consumers
must verify authority evidence independently.&lt;/p&gt;

&lt;h3 id=&quot;underlying-action-verification&quot;&gt;Underlying Action Verification&lt;/h3&gt;

&lt;p&gt;A compliance event is not proof that the underlying issuance, transfer,
freeze, KYC decision, or other action occurred. Consumers requiring that proof
must verify the referenced operation and its relationship to the record.&lt;/p&gt;

&lt;h3 id=&quot;correction-authorization&quot;&gt;Correction Authorization&lt;/h3&gt;

&lt;p&gt;Fork prevention does not determine who is entitled to correct a record. A weak
correction policy can let one recorder supersede another recorder’s assertions.
Implementations must document and enforce correction authority.&lt;/p&gt;

&lt;h3 id=&quot;long-correction-chains&quot;&gt;Long Correction Chains&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentEventIndex&lt;/code&gt; traverses on-chain correction pointers. Although chains are
linear and acyclic, a long chain can consume substantial gas or make an on-chain
call impractical. Applications should avoid unnecessary repeated corrections
and may resolve long histories off-chain.&lt;/p&gt;

&lt;h3 id=&quot;backdating&quot;&gt;Backdating&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;occurredAt&lt;/code&gt; is supplied by the recorder. Rejecting future timestamps prevents
one class of invalid input but does not establish historical accuracy. A
documented backdating limit reduces, but does not eliminate, fabricated history.&lt;/p&gt;

&lt;h3 id=&quot;privacy-and-data-protection&quot;&gt;Privacy and Data Protection&lt;/h3&gt;

&lt;p&gt;All event fields, dynamic payloads, party addresses, and URIs stored on a public
chain are permanently observable. Implementations must not place personal,
confidential, investigative, or legally restricted information on-chain merely
because the interface permits it.&lt;/p&gt;

&lt;p&gt;Public-chain deployments should use opaque or salted subject identifiers,
minimal party arrays, generalized outcomes, redacted payloads, and evidence
commitments whose preimages are distributed through appropriate access
controls. Hashing low-entropy personal data without a secret salt does not
provide meaningful privacy.&lt;/p&gt;

&lt;h3 id=&quot;evidence-availability-and-ambiguity&quot;&gt;Evidence Availability and Ambiguity&lt;/h3&gt;

&lt;p&gt;A nonzero evidence hash does not make evidence available or identify the
hashing and document scheme by itself. Implementations must document how
evidence commitments are derived and how authorized consumers obtain the
preimage.&lt;/p&gt;

&lt;h3 id=&quot;payload-confusion&quot;&gt;Payload Confusion&lt;/h3&gt;

&lt;p&gt;The log can store malformed known payloads and arbitrary unknown profiles. A
consumer that decodes without first checking &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;payloadProfileId&lt;/code&gt; can
misinterpret attacker-controlled bytes. Consumers must use profile-aware
decoding and reject malformed known profiles.&lt;/p&gt;

&lt;h3 id=&quot;event-type-and-outcome-confusion&quot;&gt;Event-Type and Outcome Confusion&lt;/h3&gt;

&lt;p&gt;The base log does not validate event-type and outcome combinations. Consumers
must not treat a stored combination as policy-approved unless the recorder’s
application enforces the applicable matrix.&lt;/p&gt;

&lt;h3 id=&quot;storage-growth-and-retrieval-costs&quot;&gt;Storage Growth and Retrieval Costs&lt;/h3&gt;

&lt;p&gt;The log is append-only and grows monotonically. Authorization, bounded dynamic
fields, reporting-frequency policy, and operational monitoring are necessary
to control storage costs and spam.&lt;/p&gt;

&lt;h3 id=&quot;event-and-storage-interpretation&quot;&gt;Event and Storage Interpretation&lt;/h3&gt;

&lt;p&gt;Off-chain indexers can reconstruct timelines from events, but on-chain
contracts cannot read historical logs. On-chain consumers must use storage
getters. Indexers should reconcile events with storage when resolving correction
chains and current state.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8328</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8328</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked Impact Snapshot Log</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8329 - Subject-Linked Impact Snapshot Log&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8329-subject-linked-impact-snapshot-log/28938&quot;&gt;https://ethereum-magicians.org/t/erc-8329-subject-linked-impact-snapshot-log/28938&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an append-only interface for
reporting quantitative impact
indicator snapshots against application-defined subjects. Each snapshot records
a signed value, decimal precision, unit, completed measurement period,
methodology commitment and location, reporter, recording time, and correction
provenance.&lt;/p&gt;

&lt;p&gt;The core interface supports per-subject storage, per-indicator indexing, exact
period lookup, and fork-free correction chains. Optional interfaces support
append-only endorsement or dispute attestations and future methodology
supersession with active and pending methodology discovery.&lt;/p&gt;

&lt;p&gt;This ERC standardizes representation and lifecycle behavior. It does not define
which indicators or methodologies are valid, verify reported measurements,
credential reporters or attestors, prevent overlapping claims, or provide an
impact score.&lt;/p&gt;

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

&lt;p&gt;Impact measurements such as emissions, carbon offsets, renewable energy,
water treatment, employment, beneficiaries, biodiversity area, and diverted
waste are commonly distributed through reports and application-specific data
formats. On-chain systems lack a common interface for associating these values
with a subject, measurement period, unit, and methodology while preserving
later corrections.&lt;/p&gt;

&lt;p&gt;A single mutable value cannot distinguish a new reporting period from a
restatement of an earlier measurement. It also erases the prior assertion when
updated. Generic attestations can represent individual claims but do not by
themselves define per-indicator time-series indexing, exact-period uniqueness,
correction chains, or methodology transitions.&lt;/p&gt;

&lt;p&gt;This ERC provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;subject-linked, period-bounded quantitative snapshots;&lt;/li&gt;
  &lt;li&gt;signed values with explicit decimals and units;&lt;/li&gt;
  &lt;li&gt;one original snapshot per exact subject, indicator, and period;&lt;/li&gt;
  &lt;li&gt;additive, fork-free corrections;&lt;/li&gt;
  &lt;li&gt;per-indicator iteration and exact-period current-state lookup;&lt;/li&gt;
  &lt;li&gt;required methodology commitments and retrieval references;&lt;/li&gt;
  &lt;li&gt;optional append-only endorsement and dispute attestations; and&lt;/li&gt;
  &lt;li&gt;optional active and scheduled methodology version discovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interfaces can be deployed independently of any token, registry, identity,
or accounting system.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;subject&lt;/strong&gt; is an application-defined entity identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;indicator&lt;/strong&gt; is an application-defined measured quantity identified by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;snapshot&lt;/strong&gt; is one reported value for an indicator, subject, and measurement
period.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;measurement period&lt;/strong&gt; is the half-open interval &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[periodStart, periodEnd)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;original snapshot&lt;/strong&gt; is the first snapshot occupying an exact subject,
indicator, and period slot.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;correction chain&lt;/strong&gt; is a linear sequence of snapshots connected by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal snapshot&lt;/strong&gt; is a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals zero.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;methodology&lt;/strong&gt; is the documented process used to measure or calculate a
reported value.&lt;/p&gt;

&lt;p&gt;An &lt;strong&gt;attestation&lt;/strong&gt; is an append-only endorsement or dispute attached to a
specific snapshot.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-value&quot;&gt;Sentinel Value&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt; identifies an original snapshot.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex == 0&lt;/code&gt; identifies a snapshot with no successor correction.&lt;/p&gt;

&lt;p&gt;Index zero is safe as the corrected-by sentinel because every correction index
is greater than the snapshot it corrects and therefore cannot be zero.&lt;/p&gt;

&lt;h3 id=&quot;core-snapshot-interface&quot;&gt;Core Snapshot Interface&lt;/h3&gt;

&lt;p&gt;A compliant log MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IImpactSnapshotLog&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IndicatorSnapshot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SnapshotRecorded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reportedBy&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IndicatorSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorSnapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorSnapshotAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestIndicatorSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentSnapshotForPeriod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodStart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;periodEnd&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;value-decimal-and-unit-semantics&quot;&gt;Value, Decimal, and Unit Semantics&lt;/h3&gt;

&lt;p&gt;The represented quantity is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;value * 10^(-decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt; is signed because an impact measurement can be negative. This ERC does
not impose a maximum decimal precision below the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8&lt;/code&gt; type limit. Consumers
MUST handle the declared precision safely and MUST NOT assume the value is
nonnegative.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt; SHOULD be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; hash of a documented canonical unit string.
Applications SHOULD use International System of Units (SI) or Unified Code for
Units of Measure (UCUM)-compatible representations when available and MUST
document exact case, spelling, pluralization, and conversion rules for custom
or zero-valued unit identifiers.&lt;/p&gt;

&lt;p&gt;This ERC does not require a nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;.
Applications requiring stricter namespaces MUST enforce and document them.&lt;/p&gt;

&lt;h3 id=&quot;measurement-periods&quot;&gt;Measurement Periods&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt; is inclusive and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt; is exclusive.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordSnapshot&lt;/code&gt; MUST revert unless:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;periodStart &amp;lt; periodEnd &amp;lt;= block.timestamp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Only completed measurement periods can be recorded.&lt;/p&gt;

&lt;p&gt;An exact period slot is identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, indicatorId, periodStart,
periodEnd)&lt;/code&gt;. A log MUST accept at most one original snapshot for an exact slot.
Once occupied, revisions to that slot MUST use correction provenance.&lt;/p&gt;

&lt;p&gt;Different periods MAY overlap. This ERC does not determine whether overlapping
measurements are additive, duplicative, or methodologically compatible.&lt;/p&gt;

&lt;h3 id=&quot;recording-semantics&quot;&gt;Recording Semantics&lt;/h3&gt;

&lt;p&gt;Snapshot indices MUST be zero-based and scoped per &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. The returned
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotIndex&lt;/code&gt; MUST equal the subject’s snapshot count before the new snapshot
is appended.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recordSnapshot&lt;/code&gt; MUST be restricted to authorized reporters. The authorization
mechanism is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted snapshot, the log MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;store the supplied snapshot fields;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reportedBy&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reportedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to zero;&lt;/li&gt;
  &lt;li&gt;append the snapshot index to the indicator-specific index;&lt;/li&gt;
  &lt;li&gt;make the snapshot discoverable for its exact period; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SnapshotRecorded&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MUST NOT be
empty.&lt;/p&gt;

&lt;p&gt;The methodology hash MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256&lt;/code&gt; of the exact methodology document
bytes under a documented representation. Consumers MUST retrieve the document
and reproduce the commitment before relying on it.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original snapshot MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A correction MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;identify an earlier snapshot under the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt; as its target;&lt;/li&gt;
  &lt;li&gt;target a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; is zero; and&lt;/li&gt;
  &lt;li&gt;be authorized under the implementation’s documented correction policy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a correction is accepted, the log MUST set the target snapshot’s
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to the new snapshot index. No other target field may change.&lt;/p&gt;

&lt;p&gt;Each snapshot can be corrected at most once, preventing forks. A correction
snapshot can itself be corrected, producing a linear chain.&lt;/p&gt;

&lt;p&gt;The correction policy MUST NOT permit an ordinary reporter to correct another
reporter’s snapshot merely because both addresses can report. It MAY authorize
the original reporter, a designated corrector, or an administrator.&lt;/p&gt;

&lt;p&gt;A correction MAY change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;value&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;, methodology, and reporter,
subject to the active methodology rules of an implementation supporting the
methodology extension.&lt;/p&gt;

&lt;h3 id=&quot;snapshot-queries&quot;&gt;Snapshot Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSnapshot&lt;/code&gt; MUST return the complete stored snapshot and MUST revert when
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotIndex &amp;gt;= snapshotCount(subjectId)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotCount&lt;/code&gt; MUST return the number of snapshots recorded for a subject.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotCount&lt;/code&gt; MUST return the number of snapshots recorded for an
exact subject and indicator, including corrections.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotAt&lt;/code&gt; MUST return the per-subject snapshot index at the
specified zero-based indicator ordinal and MUST revert when the ordinal is
outside the indicator-specific index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt; MUST return the most recently recorded snapshot
index for the indicator and MUST revert when none exists. It describes
recording order, not the greatest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt;, and does not necessarily identify
the current value for a particular period.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; MUST return the terminal snapshot index for the
exact subject, indicator, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodStart&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;periodEnd&lt;/code&gt;. It MUST revert when no
snapshot occupies that period slot.&lt;/p&gt;

&lt;p&gt;Consumers querying a specific reporting period SHOULD use
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; rather than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;indicator-identifiers&quot;&gt;Indicator Identifiers&lt;/h3&gt;

&lt;p&gt;The following indicator identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CARBON_OFFSET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:CARBON_OFFSET&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CARBON_EMITTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:CARBON_EMITTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENERGY_GENERATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:ENERGY_GENERATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ENERGY_SAVED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:ENERGY_SAVED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WATER_TREATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:WATER_TREATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JOBS_CREATED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:JOBS_CREATED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BENEFICIARIES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:BENEFICIARIES&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BIODIVERSITY_AREA&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:BIODIVERSITY_AREA&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WASTE_DIVERTED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8329:INDICATOR:WASTE_DIVERTED&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Custom indicators SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keccak256(&quot;ERC-8329:INDICATOR:&amp;lt;NAMESPACE&amp;gt;:&amp;lt;NAME&amp;gt;:&amp;lt;VERSION&amp;gt;&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Applications MUST document indicator definitions, boundaries, calculation
rules, and any mapping to external taxonomies. A generic identifier such as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keccak256(&quot;CUSTOM&quot;)&lt;/code&gt; SHOULD NOT be used because it does not provide semantic
separation.&lt;/p&gt;

&lt;h3 id=&quot;unit-identifiers&quot;&gt;Unit Identifiers&lt;/h3&gt;

&lt;p&gt;The following unit identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_TCO2E&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tCO2e&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_KWH&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;kWh&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_M3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_FTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;FTE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_PERSONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;persons&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_HECTARES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;hectares&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UNIT_TONNES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;tonnes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UNIT_FTE&lt;/code&gt; uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FTE&lt;/code&gt; to denote full-time equivalent; the preimage string
remains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;FTE&quot;&lt;/code&gt; for stability.&lt;/p&gt;

&lt;p&gt;The defined indicator identifiers do not mandate one unit. Reporters and
consumers MUST inspect the stored unit and methodology rather than inferring a
unit from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorId&lt;/code&gt; alone.&lt;/p&gt;

&lt;h3 id=&quot;attestation-extension&quot;&gt;Attestation Extension&lt;/h3&gt;

&lt;p&gt;Attestation is OPTIONAL. An implementation supporting it MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IImpactAttestation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Attestation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SnapshotAttested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endorsed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;evidenceURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAttestation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;attestationIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Attestation&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestSnapshot&lt;/code&gt; MUST reject an unknown snapshot and a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceHash&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;evidenceURI&lt;/code&gt; MAY be empty.&lt;/p&gt;

&lt;p&gt;The implementation MUST set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestor&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;, set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestedAt&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;, append the attestation, emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SnapshotAttested&lt;/code&gt;, and
return its zero-based per-snapshot index.&lt;/p&gt;

&lt;p&gt;The reporter address stored on the snapshot MUST NOT attest that snapshot.
This is address-level separation only; it does not establish organizational,
affiliate, financial, or legal independence.&lt;/p&gt;

&lt;p&gt;Attestations MUST be immutable and non-deletable. The same attestor MAY submit
multiple attestations for the same snapshot, including a later assessment that
differs from an earlier one. Consumers MUST evaluate the complete history.&lt;/p&gt;

&lt;p&gt;Attestations MAY be added to corrected or nonterminal snapshots. Consumers MUST
decide whether an attestation to an earlier snapshot applies to any correction.
This ERC does not carry attestations forward automatically.&lt;/p&gt;

&lt;p&gt;Attestor authorization and credentialing are implementation defined and MUST
be documented.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;attestationCount&lt;/code&gt; MUST return the number of attestations for the exact snapshot.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAttestation&lt;/code&gt; MUST return the requested record and MUST revert when the
attestation index is outside that snapshot’s history.&lt;/p&gt;

&lt;h3 id=&quot;methodology-versioning-extension&quot;&gt;Methodology Versioning Extension&lt;/h3&gt;

&lt;p&gt;Methodology versioning is OPTIONAL. An implementation supporting it MUST
implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMethodologyVersioning&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MethodologySuperseded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;supersedeMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;activeMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pendingMethodology&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indicatorId&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newMethodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;effectiveFromOrdinal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pending&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;methodology-initialization-and-enforcement&quot;&gt;Methodology Initialization and Enforcement&lt;/h3&gt;

&lt;p&gt;The first snapshot for a subject and indicator MUST initialize its active
methodology to the snapshot’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After initialization, each new snapshot for that subject and indicator MUST use
the methodology hash active at its indicator-specific ordinal.&lt;/p&gt;

&lt;p&gt;The snapshot’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MUST remain nonempty, but this ERC does not
require it to equal the URI returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt;. Multiple locators
can reference the same committed methodology bytes. Consumers MUST verify the
retrieved bytes against the active hash.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt; MUST return the methodology required for the next snapshot.
Before initialization, it MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; and an empty URI.&lt;/p&gt;

&lt;h3 id=&quot;methodology-supersession&quot;&gt;Methodology Supersession&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supersedeMethodology&lt;/code&gt; MUST be restricted under a documented authorization
policy and MUST revert unless:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;a methodology has already been initialized;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldMethodologyHash&lt;/code&gt; equals the active methodology;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newMethodologyHash&lt;/code&gt; is nonzero;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newMethodologyURI&lt;/code&gt; is nonempty;&lt;/li&gt;
  &lt;li&gt;no future supersession is already pending; and&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt; is greater than or equal to the current
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;indicatorSnapshotCount&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt; equals the current indicator count, the new
methodology becomes active immediately for the next snapshot.&lt;/p&gt;

&lt;p&gt;If it is greater than the current count, the supersession is pending. Existing
snapshots and snapshots before the effective ordinal continue to use the old
methodology. The new methodology becomes active when the current indicator
count reaches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;effectiveFromOrdinal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Every successful supersession MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MethodologySuperseded&lt;/code&gt;. Existing
snapshot fields MUST NOT change.&lt;/p&gt;

&lt;p&gt;Implementations MAY impose a documented maximum future lookahead.&lt;/p&gt;

&lt;h3 id=&quot;pending-methodology-discovery&quot;&gt;Pending Methodology Discovery&lt;/h3&gt;

&lt;p&gt;While a future supersession has not reached its effective ordinal,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingMethodology&lt;/code&gt; MUST return the scheduled hash, URI, ordinal, and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pending == true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When no supersession is scheduled, or once its effective ordinal has been
reached, it MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;, an empty URI, zero, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the ordinal has been reached, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;activeMethodology&lt;/code&gt; MUST expose the new
methodology even if no state-changing call has yet persisted an internal
transition.&lt;/p&gt;

&lt;p&gt;Historical values recalculated under a new methodology MUST be submitted as
corrections. They MUST NOT mutate existing snapshots.&lt;/p&gt;

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

&lt;p&gt;Compliant core logs MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(IImpactSnapshotLog).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations supporting optional extensions MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the
corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IImpactAttestation&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IMethodologyVersioning&lt;/code&gt; interface IDs.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish measurement
accuracy, methodology validity, reporter or attestor credentials, evidence
quality, or independence.&lt;/p&gt;

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

&lt;h3 id=&quot;why-append-only-snapshots&quot;&gt;Why Append-Only Snapshots?&lt;/h3&gt;

&lt;p&gt;Impact data changes through new periods, corrected measurements, and revised
methodologies. Append-only storage preserves each assertion and makes revisions
visible instead of replacing history.&lt;/p&gt;

&lt;h3 id=&quot;why-one-original-per-exact-period&quot;&gt;Why One Original Per Exact Period?&lt;/h3&gt;

&lt;p&gt;Allowing multiple unrelated originals for the same indicator and exact period
would create competing current values. Requiring later revisions to use
correction provenance provides one resolvable chain.&lt;/p&gt;

&lt;h3 id=&quot;why-permit-overlapping-periods&quot;&gt;Why Permit Overlapping Periods?&lt;/h3&gt;

&lt;p&gt;Monthly, quarterly, annual, project-phase, and rolling measurements can
legitimately overlap. The interface cannot determine whether an overlap is
valid. Consumers aggregating values must apply methodology-specific rules to
avoid double counting.&lt;/p&gt;

&lt;h3 id=&quot;why-use-int256&quot;&gt;Why Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256&lt;/code&gt;?&lt;/h3&gt;

&lt;p&gt;Measurements can be negative. Net emissions, energy savings relative to a
baseline, or other indicators can move in either direction.&lt;/p&gt;

&lt;h3 id=&quot;why-both-latest-and-period-specific-queries&quot;&gt;Why Both Latest and Period-Specific Queries?&lt;/h3&gt;

&lt;p&gt;The most recently recorded snapshot can concern an old period, such as a late
correction. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestIndicatorSnapshot&lt;/code&gt; supports monitoring recording activity,
while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotForPeriod&lt;/code&gt; resolves the current value for an exact
period.&lt;/p&gt;

&lt;h3 id=&quot;why-require-methodology-metadata&quot;&gt;Why Require Methodology Metadata?&lt;/h3&gt;

&lt;p&gt;A value and unit are insufficient without the process that produced them.
Requiring both a commitment and a retrieval reference makes the declared
methodology independently verifiable when the document remains available.&lt;/p&gt;

&lt;h3 id=&quot;why-methodology-versioning-as-an-extension&quot;&gt;Why Methodology Versioning as an Extension?&lt;/h3&gt;

&lt;p&gt;Some deployments need only immutable per-snapshot methodology references.
Others require a governed active methodology for future reports. Separating the
extension allows the core log to remain usable without prescribing methodology
governance.&lt;/p&gt;

&lt;h3 id=&quot;why-attestation-as-an-extension&quot;&gt;Why Attestation as an Extension?&lt;/h3&gt;

&lt;p&gt;Not every deployment requires endorsement or dispute records. The optional
interface permits independent assessment histories without making credential
policy part of the core snapshot log.&lt;/p&gt;

&lt;h3 id=&quot;why-not-replace-earlier-attestations&quot;&gt;Why Not Replace Earlier Attestations?&lt;/h3&gt;

&lt;p&gt;An attestor’s changed view is itself relevant history. Appending the later
assessment preserves both statements and lets consumers apply their own
recency and credential policies.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token,
registry, credential, attestation, or accounting standards.&lt;/p&gt;

&lt;p&gt;An existing application can deploy a companion snapshot log and use its own
application-defined subject namespace. No token contract changes are required
unless the token itself records snapshots.&lt;/p&gt;

&lt;p&gt;Implementations can adopt only the core interface or additionally expose either
optional extension. Consumers use ERC-165 to detect supported interfaces.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;zero-based per-subject indexing and subject isolation;&lt;/li&gt;
  &lt;li&gt;per-indicator counts, ordinals, and latest-recorded lookup;&lt;/li&gt;
  &lt;li&gt;completed, zero-length, and future period validation;&lt;/li&gt;
  &lt;li&gt;positive, zero, and negative values with varying decimals;&lt;/li&gt;
  &lt;li&gt;methodology hash and URI requirements;&lt;/li&gt;
  &lt;li&gt;one original per exact period;&lt;/li&gt;
  &lt;li&gt;overlapping but nonidentical periods;&lt;/li&gt;
  &lt;li&gt;correction bounds, authorization, period matching, and fork prevention;&lt;/li&gt;
  &lt;li&gt;multi-step correction chains and exact-period terminal lookup;&lt;/li&gt;
  &lt;li&gt;methodology initialization and active-methodology enforcement;&lt;/li&gt;
  &lt;li&gt;immediate and future methodology supersession;&lt;/li&gt;
  &lt;li&gt;pending methodology hash, URI, ordinal, and activation discovery;&lt;/li&gt;
  &lt;li&gt;pending-supersession exclusivity and implementation lookahead limits;&lt;/li&gt;
  &lt;li&gt;attestation evidence requirements and empty evidence URIs;&lt;/li&gt;
  &lt;li&gt;same-address self-attestation rejection;&lt;/li&gt;
  &lt;li&gt;repeated endorsement and dispute histories;&lt;/li&gt;
  &lt;li&gt;attestations to current and corrected snapshots;&lt;/li&gt;
  &lt;li&gt;unknown snapshot and attestation queries; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection for every supported interface.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A Solidity reference implementation, constants library, example integrations,
unit tests, Medusa property tests, deployment scripts, and independent audit are
linked from the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses reporter, attestor, and administrator roles;&lt;/li&gt;
  &lt;li&gt;allows a reporter to correct its own snapshot and an administrator-reporter
to correct another reporter’s snapshot;&lt;/li&gt;
  &lt;li&gt;rejects completed-period duplicates unless correction provenance is used;&lt;/li&gt;
  &lt;li&gt;implements all three interfaces;&lt;/li&gt;
  &lt;li&gt;blocks same-address self-attestation; and&lt;/li&gt;
  &lt;li&gt;limits scheduled methodology supersession to 1,000 future indicator
ordinals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role assignments and the 1,000-ordinal lookahead are reference deployment
choices rather than core interface requirements.&lt;/p&gt;

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

&lt;h3 id=&quot;reporter-trust&quot;&gt;Reporter Trust&lt;/h3&gt;

&lt;p&gt;The log proves that an authorized address reported a value. It does not verify
the measurement, source data, calculation, unit, period boundaries, or
methodology application. False data remains false when recorded immutably.&lt;/p&gt;

&lt;h3 id=&quot;methodology-integrity-and-availability&quot;&gt;Methodology Integrity and Availability&lt;/h3&gt;

&lt;p&gt;A methodology commitment is useful only when consumers can obtain the exact
document representation and reproduce its hash. A URI can disappear, change
content, require authorization, or expose sensitive information. Deployments
should use durable storage and document the hashing representation.&lt;/p&gt;

&lt;h3 id=&quot;methodology-governance&quot;&gt;Methodology Governance&lt;/h3&gt;

&lt;p&gt;An authorized party can supersede a methodology with one that produces more
favorable results. Events and pending-methodology queries make the transition
visible but do not establish its legitimacy. Consumers must evaluate
methodology governance independently.&lt;/p&gt;

&lt;h3 id=&quot;correction-authorization-and-chain-length&quot;&gt;Correction Authorization and Chain Length&lt;/h3&gt;

&lt;p&gt;A weak correction policy can let one reporter supersede another’s measurement.
Implementations must document correction authority.&lt;/p&gt;

&lt;p&gt;Period lookup traverses correction pointers. Although chains are linear and
acyclic, excessive corrections can make on-chain resolution expensive.&lt;/p&gt;

&lt;h3 id=&quot;attestor-credentials-and-independence&quot;&gt;Attestor Credentials and Independence&lt;/h3&gt;

&lt;p&gt;Blocking the exact reporter address prevents only direct self-attestation. The
same organization can control multiple addresses, and an attestor role does not
prove professional qualification, financial independence, or legal authority.
Consumers must evaluate credential and conflict policies.&lt;/p&gt;

&lt;h3 id=&quot;conflicting-attestations&quot;&gt;Conflicting Attestations&lt;/h3&gt;

&lt;p&gt;The interface permits multiple endorsements and disputes without computing a
consensus result. Counting addresses is not a reliable trust model because
addresses are cheap and credentials can differ. Consumers need an external
attestor-selection and weighting policy.&lt;/p&gt;

&lt;h3 id=&quot;double-counting-and-overlapping-claims&quot;&gt;Double Counting and Overlapping Claims&lt;/h3&gt;

&lt;p&gt;Exact-period uniqueness applies only within one subject and indicator slot.
Overlapping periods, related indicators, multiple subjects, and independent
registries can represent the same underlying impact. Consumers must reconcile
boundaries and methodologies before aggregation.&lt;/p&gt;

&lt;h3 id=&quot;privacy&quot;&gt;Privacy&lt;/h3&gt;

&lt;p&gt;Subjects, values, periods, methodology URIs, and attestation evidence can reveal
commercial, personal, geographic, or site-sensitive information. Public-chain
deployments should use opaque subject identifiers, redacted documents, and
access-controlled evidence distribution where appropriate. Hashing low-entropy
sensitive data without a secret salt does not provide meaningful privacy.&lt;/p&gt;

&lt;h3 id=&quot;unit-and-decimal-handling&quot;&gt;Unit and Decimal Handling&lt;/h3&gt;

&lt;p&gt;Consumers that ignore units, decimals, sign, or conversion rules can produce
materially incorrect aggregates. Implementations should use checked arithmetic,
explicit normalization, and methodology-aware conversion.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Completed-period validation uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;, which block producers can
influence within protocol bounds. Applications requiring exact wall-clock
cutoffs must account for that uncertainty.&lt;/p&gt;

&lt;h3 id=&quot;storage-growth&quot;&gt;Storage Growth&lt;/h3&gt;

&lt;p&gt;Snapshots and attestations are append-only. Authorization, reporting-frequency
policy, and operational monitoring are necessary to control storage costs and
spam.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8329</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8329</guid>
      </item>
      
    
      
      
      <item>
        <title>Subject-Linked NAV Snapshot Oracle</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8330 - Subject-Linked NAV Snapshot Oracle&lt;/strong&gt; is in Last Call status. It is authored by Chris Turner &lt;c.turner@kula.com&gt;, David Hay (@david-hay), Reagan Simpson (@krumg111), Collins Musyimi (@Musyimi97) and was originally created 2026-07-05. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://ethereum-magicians.org/t/erc-8330-subject-linked-nav-snapshot-oracle/28939&quot;&gt;https://ethereum-magicians.org/t/erc-8330-subject-linked-nav-snapshot-oracle/28939&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;This Ethereum Request for Comments (ERC) defines an interface for publishing
and querying subject-linked net asset value (NAV) snapshots. Each stream is
keyed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; and
has one configured NAV basis. Snapshots include signed NAV, decimal precision,
valuation and publication timestamps, provider attribution, methodology
references, and correction provenance.&lt;/p&gt;

&lt;p&gt;The core interface supports raw and staleness-aware latest-value queries,
provider-specific history, correction-chain resolution, and administrative
invalidation that preserves records while excluding invalid snapshots from
current-value queries. An optional aggregation interface defines deterministic
lower-median aggregation across provider submissions sharing a valuation
timestamp.&lt;/p&gt;

&lt;p&gt;This ERC standardizes publication and query semantics. It does not calculate
NAV, credential providers, verify methodologies, establish asset backing, or
guarantee that NAV is an executable market or redemption price.&lt;/p&gt;

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

&lt;p&gt;Periodic valuations for funds, private credit, real estate, infrastructure,
commodities, and other illiquid or administratively priced assets differ from
continuous exchange prices. Consumers need to know what the value represents,
when the underlying valuation was measured, when it was published, who supplied
it, and whether it is too old for the intended use.&lt;/p&gt;

&lt;p&gt;Existing price and quote interfaces do not necessarily preserve valuation
history, provider identity, methodology references, restatement provenance, or
separate publication-age and valuation-age checks. Bespoke NAV contracts also
use incompatible stream keys and latest-value semantics.&lt;/p&gt;

&lt;p&gt;This ERC provides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;independent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; NAV streams;&lt;/li&gt;
  &lt;li&gt;stream-level basis configuration preventing provider disagreement over
per-unit, per-share, or total interpretation;&lt;/li&gt;
  &lt;li&gt;provider-attributed historical snapshots;&lt;/li&gt;
  &lt;li&gt;one original provider submission per valuation timestamp;&lt;/li&gt;
  &lt;li&gt;fork-free corrections and current-chain helpers;&lt;/li&gt;
  &lt;li&gt;administrative invalidation for compromised or disputed terminal snapshots;&lt;/li&gt;
  &lt;li&gt;separate publication and valuation staleness signals; and&lt;/li&gt;
  &lt;li&gt;optional deterministic aggregation with quorum and deviation reporting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interface can serve vaults, settlement systems, reporting applications, and
other consumers while leaving valuation policy and provider governance to each
deployment.&lt;/p&gt;

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

&lt;p&gt;The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”,
“SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and
“OPTIONAL” in this document are to be interpreted as described in
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc2119&quot;&gt;RFC 2119&lt;/a&gt; and
&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;A &lt;strong&gt;stream&lt;/strong&gt; is the namespace identified by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;NAV basis&lt;/strong&gt; states whether NAV represents one underlying unit, one share or
token, or the total value of the subject.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;provider&lt;/strong&gt; is the address recorded as publishing a snapshot.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;valuation timestamp&lt;/strong&gt; is the asserted as-of time of the valuation.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;publication timestamp&lt;/strong&gt; is the block timestamp at which the snapshot was
recorded.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;terminal snapshot&lt;/strong&gt; is a snapshot whose &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; equals
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;current snapshot&lt;/strong&gt; is a terminal snapshot that has not been invalidated.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;publication heartbeat&lt;/strong&gt; is the maximum accepted time since publication.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;maximum valuation age&lt;/strong&gt; is the maximum accepted time since the valuation
timestamp.&lt;/p&gt;

&lt;h3 id=&quot;sentinel-values&quot;&gt;Sentinel Values&lt;/h3&gt;

&lt;p&gt;Implementations MUST use:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NO_CORRECTED_BY&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTION&lt;/code&gt; identifies an original snapshot. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt; identifies a
snapshot with no successor correction.&lt;/p&gt;

&lt;p&gt;Index zero is safe as the corrected-by sentinel because a correction index is
always greater than its target and therefore cannot be zero.&lt;/p&gt;

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

&lt;p&gt;A compliant oracle MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INAVSnapshotOracle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctedByIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVPublished&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StalenessConfigUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVBasisConfigured&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVSnapshotInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidatedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodologyURI&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;correctsIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setNAVBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invalidateSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSnapshotInvalidated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setStalenessConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;streamNAVBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAVStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isPublishStale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValuationStale&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentSnapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSnapshotCurrent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestNAVByProvider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NAVSnapshot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSnapshotCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSnapshotAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ordinal&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;heartbeat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxValuationAge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;stream-scope&quot;&gt;Stream Scope&lt;/h3&gt;

&lt;p&gt;Snapshot indices MUST be zero-based and scoped independently to each
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(subjectId, currency)&lt;/code&gt; stream.&lt;/p&gt;

&lt;p&gt;This ERC does not require nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currency&lt;/code&gt; values.
Applications requiring stricter namespaces MUST enforce and document them.&lt;/p&gt;

&lt;h3 id=&quot;nav-basis&quot;&gt;NAV Basis&lt;/h3&gt;

&lt;p&gt;The following basis identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PER_UNIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:PER_UNIT&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PER_SHARE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:PER_SHARE&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TOTAL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:NAV_BASIS:TOTAL&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_UNIT&lt;/code&gt; represents one unit of the underlying asset. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_SHARE&lt;/code&gt; represents
one share or token in a fund or pool. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL&lt;/code&gt; represents the total NAV of the
subject.&lt;/p&gt;

&lt;p&gt;An authorized configurer MUST call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setNAVBasis&lt;/code&gt; before the first publication
to a stream. The function MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;accept only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_UNIT&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PER_SHARE&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TOTAL&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;reject a stream that already contains snapshots;&lt;/li&gt;
  &lt;li&gt;reject a stream whose basis was already configured;&lt;/li&gt;
  &lt;li&gt;store the basis permanently; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVBasisConfigured&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;streamNAVBasis&lt;/code&gt; MUST return the configured basis or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt; for an
unconfigured stream.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST reject an unconfigured stream and any supplied basis that
does not equal its configured basis.&lt;/p&gt;

&lt;p&gt;Provider-selected basis changes are prohibited. Stream-level configuration
prevents incompatible submissions from disabling aggregation at a shared
valuation timestamp.&lt;/p&gt;

&lt;h3 id=&quot;nav-and-decimal-semantics&quot;&gt;NAV and Decimal Semantics&lt;/h3&gt;

&lt;p&gt;The represented NAV is:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nav * 10^(-decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nav&lt;/code&gt; is signed because liabilities can exceed assets. Consumers MUST handle
negative and zero values explicitly.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST reject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals &amp;gt; 18&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nav == type(int256).min&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;a magnitude greater than:&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This bound ensures that a conforming aggregation implementation can safely
normalize every accepted value to 18 decimal places.&lt;/p&gt;

&lt;h3 id=&quot;currency-identifiers&quot;&gt;Currency Identifiers&lt;/h3&gt;

&lt;p&gt;The following fiat currency identifiers are defined:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;USD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:USD&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EUR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:EUR&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GBP&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:GBP&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;KES&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:KES&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ZMW&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:ZMW&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additional ISO 4217 currencies SHOULD use:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;keccak256(&quot;ERC-8330:CURRENCY:&amp;lt;CODE&amp;gt;&quot;)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Token-denominated streams SHOULD derive currency as:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;keccak256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;ERC-8330:CURRENCY:TOKEN&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;chainId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;tokenAddress&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Including both chain ID and token address prevents equal addresses on different
chains from sharing a currency identifier.&lt;/p&gt;

&lt;p&gt;Other denominations SHOULD use an application-documented, domain-separated
identifier and MUST NOT reuse an ISO code unless the denomination is that fiat
currency.&lt;/p&gt;

&lt;h3 id=&quot;publication-semantics&quot;&gt;Publication Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt; MUST be restricted to authorized providers. Provider authorization
is implementation defined and MUST be documented.&lt;/p&gt;

&lt;p&gt;For every accepted snapshot, the oracle MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;provider&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;set &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishedAt&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64(block.timestamp)&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;initialize &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NO_CORRECTED_BY&lt;/code&gt;;&lt;/li&gt;
  &lt;li&gt;append the snapshot to the stream and provider history;&lt;/li&gt;
  &lt;li&gt;update current-value and provider/timestamp indexes;&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVPublished&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;return the new stream-scoped index.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt; MUST NOT be greater than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyHash&lt;/code&gt; MUST NOT be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32(0)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;methodologyURI&lt;/code&gt; MAY be empty only when the deployment documents how consumers
retrieve the exact methodology representation out of band. The hash derivation
MUST be documented. It MAY commit to raw document bytes or a deterministic
document-bundle commitment.&lt;/p&gt;

&lt;p&gt;The oracle MUST reject the call if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt; cannot be represented as
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint64&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;provider-and-valuation-uniqueness&quot;&gt;Provider and Valuation Uniqueness&lt;/h3&gt;

&lt;p&gt;A provider MAY publish at most one current original snapshot for an exact
stream and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If that provider/timestamp slot is occupied, a revision MUST use correction
provenance. Other providers MAY publish independent originals for the same
stream and valuation timestamp.&lt;/p&gt;

&lt;h3 id=&quot;correction-semantics&quot;&gt;Correction Semantics&lt;/h3&gt;

&lt;p&gt;An original snapshot MUST use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex == NO_CORRECTION&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A correction MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;identify an earlier snapshot in the same stream;&lt;/li&gt;
  &lt;li&gt;target a terminal, non-invalidated snapshot;&lt;/li&gt;
  &lt;li&gt;be published by the same provider as the target;&lt;/li&gt;
  &lt;li&gt;use the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;navBasis&lt;/code&gt; as the target; and&lt;/li&gt;
  &lt;li&gt;target the provider’s current snapshot for that valuation timestamp.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When accepted, the target’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; MUST be set to the new snapshot
index. No other target field may change.&lt;/p&gt;

&lt;p&gt;Before invalidation, each snapshot can have at most one successor correction.
A correction can itself be corrected, creating a linear current chain. A
correction MAY change NAV, decimals, methodology, and methodology URI.&lt;/p&gt;

&lt;h3 id=&quot;invalidation&quot;&gt;Invalidation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;invalidateSnapshot&lt;/code&gt; MUST be restricted under a documented administrative or
governance policy. It MUST reject a zero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reasonHash&lt;/code&gt;, unknown snapshot,
nonterminal snapshot, or already invalidated snapshot.&lt;/p&gt;

&lt;p&gt;On success, the oracle MUST:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;preserve the invalidated snapshot record;&lt;/li&gt;
  &lt;li&gt;permanently mark it invalidated;&lt;/li&gt;
  &lt;li&gt;exclude it from latest-value, provider-latest, current-chain, quorum,
aggregation, and deviation calculations defined by the optional Aggregation
Extension below;&lt;/li&gt;
  &lt;li&gt;recompute affected latest and quorum pointers; and&lt;/li&gt;
  &lt;li&gt;emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVSnapshotInvalidated&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If an original snapshot is invalidated, its provider/timestamp slot MUST become
available for a replacement original.&lt;/p&gt;

&lt;p&gt;If a correction is invalidated, its direct predecessor MUST become terminal
again and the provider/timestamp slot MUST point to that predecessor. The
provider can then publish a replacement correction.&lt;/p&gt;

&lt;p&gt;In a longer correction chain, invalidating the terminal restores only its
direct predecessor. Administrators MAY unwind additional snapshots by
invalidating each newly restored terminal in turn.&lt;/p&gt;

&lt;p&gt;Invalidation does not erase &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; history. Replacement corrections
can create multiple historical records that reference the same predecessor,
but only one non-invalidated branch can be current. Consumers reconstructing
history MUST account for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVSnapshotInvalidated&lt;/code&gt; events.&lt;/p&gt;

&lt;p&gt;An invalidated snapshot MUST NOT be corrected or restored.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSnapshotInvalidated&lt;/code&gt; MUST revert for an unknown index and otherwise return
the permanent invalidation state.&lt;/p&gt;

&lt;h3 id=&quot;current-chain-queries&quot;&gt;Current-Chain Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentSnapshotIndex&lt;/code&gt; MUST revert for an unknown index. It MUST follow
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctedByIndex&lt;/code&gt; to a terminal snapshot and return that index only if the
terminal is not invalidated. It MUST revert when no current terminal remains.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSnapshotCurrent&lt;/code&gt; MUST revert for an unknown index and otherwise return
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; only when the snapshot is terminal and not invalidated.&lt;/p&gt;

&lt;h3 id=&quot;latest-nav-queries&quot;&gt;Latest NAV Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; MUST return the current snapshot with the greatest
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valuationTimestamp&lt;/code&gt;, regardless of staleness. When multiple current snapshots
share that valuation timestamp, it MUST return the most recently published one;
if publication timestamps are equal, the greater snapshot index wins.&lt;/p&gt;

&lt;p&gt;A late correction to an older valuation timestamp MUST NOT replace a current
snapshot with a later valuation timestamp as the stream’s latest NAV.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; MUST revert when no current snapshot exists.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVByProvider&lt;/code&gt; MUST apply the same valuation and publication ordering to
that provider’s current snapshots and MUST revert when the provider has no
current snapshot.&lt;/p&gt;

&lt;h3 id=&quot;historical-queries&quot;&gt;Historical Queries&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getSnapshot&lt;/code&gt; MUST return the preserved record for any valid index, including a
corrected or invalidated snapshot, and MUST revert for an unknown index.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapshotCount&lt;/code&gt; MUST include every published snapshot, including corrections
and invalidated records.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotCount&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotAt&lt;/code&gt; MUST expose the provider’s
complete publication history, including corrected and invalidated snapshots.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSnapshotAt&lt;/code&gt; MUST revert for an out-of-range ordinal.&lt;/p&gt;

&lt;h3 id=&quot;staleness-configuration&quot;&gt;Staleness Configuration&lt;/h3&gt;

&lt;p&gt;An authorized configurer MUST be able to set a nonzero publication &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heartbeat&lt;/code&gt;
and nonzero &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuationAge&lt;/code&gt; independently for each stream. Successful changes
MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StalenessConfigUpdated&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heartbeat&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuationAge&lt;/code&gt; MUST return zero while the corresponding
value is unconfigured.&lt;/p&gt;

&lt;p&gt;Configuration authorization is implementation defined and MUST be documented.&lt;/p&gt;

&lt;h3 id=&quot;staleness-semantics&quot;&gt;Staleness Semantics&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; MUST return the same snapshot selected by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; plus two
independent flags:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;isPublishStale = block.timestamp &amp;gt; publishedAt + heartbeat
isValuationStale =
    block.timestamp &amp;gt; valuationTimestamp + maxValuationAge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A value is not stale exactly at its threshold boundary.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; MUST revert when either staleness threshold is unconfigured or
when no current snapshot exists. It MUST NOT mutate state or emit events.&lt;/p&gt;

&lt;p&gt;Consumers MUST evaluate both flags. Recent publication of an old valuation can
be publication-fresh but valuation-stale.&lt;/p&gt;

&lt;h3 id=&quot;aggregation-extension&quot;&gt;Aggregation Extension&lt;/h3&gt;

&lt;p&gt;Aggregation is OPTIONAL. An implementation supporting it MUST implement:&lt;/p&gt;

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

&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INAVAggregation&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NAVDeviationDetected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minNav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxNav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AggregationConfigUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThresholdBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setAggregationConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThresholdBps&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aggregatedNAV&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isPublishStale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isValuationStale&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSubmissionCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;providerSubmissionAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;int256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;navBasis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;valuationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;publishedAt&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;latestAggregationTimestamp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deviationThreshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;subjectId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currency&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;aggregation-configuration&quot;&gt;Aggregation Configuration&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setAggregationConfig&lt;/code&gt; MUST be restricted to authorized configurers. It MUST
reject a zero quorum and a deviation threshold greater than 10,000 basis
points. Implementations MAY impose a documented maximum provider count and MUST
reject a quorum above that maximum.&lt;/p&gt;

&lt;p&gt;Successful configuration MUST emit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AggregationConfigUpdated&lt;/code&gt; and MUST account
for historical timestamps that already satisfy the new quorum.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quorum&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deviationThreshold&lt;/code&gt; MUST return zero while unconfigured.&lt;/p&gt;

&lt;h3 id=&quot;eligible-provider-submissions&quot;&gt;Eligible Provider Submissions&lt;/h3&gt;

&lt;p&gt;For one valuation timestamp, at most one submission per provider is eligible.
That submission is the provider’s current snapshot for the timestamp.
Corrected, invalidated, and detached historical snapshots MUST be excluded.&lt;/p&gt;

&lt;p&gt;A valuation timestamp is aggregation-eligible when its number of eligible
providers is at least the configured quorum.&lt;/p&gt;

&lt;p&gt;The latest aggregation timestamp MUST be the greatest eligible valuation
timestamp, not the timestamp of the most recent publication.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestAggregationTimestamp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionCount&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionAt&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST revert when quorum is
unconfigured or no valuation timestamp meets quorum.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionCount&lt;/code&gt; MUST return the eligible provider count at the latest
aggregation timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;providerSubmissionAt&lt;/code&gt; MUST return eligible submissions in provider first-seen
order for that timestamp and MUST revert when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;index&lt;/code&gt; is outside the eligible
set.&lt;/p&gt;

&lt;h3 id=&quot;median-aggregation&quot;&gt;Median Aggregation&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST normalize all eligible values to the greatest submitted
decimal precision:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;normalizedNav = nav * 10^(maxDecimals - decimals)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It MUST sort normalized values in ascending order and return:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;values[(providerCount - 1) / 2]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This selects the lower median for an even provider count.&lt;/p&gt;

&lt;p&gt;The returned basis MUST equal the configured stream basis. The returned
valuation timestamp MUST equal the latest aggregation timestamp. The returned
provider count MUST equal the number of eligible submissions.&lt;/p&gt;

&lt;p&gt;For aggregate publication staleness, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishedAt&lt;/code&gt; MUST be treated as the
greatest publication timestamp among eligible submissions. Aggregate valuation
staleness uses the shared valuation timestamp.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; MUST revert until both staleness thresholds are configured.&lt;/p&gt;

&lt;h3 id=&quot;deviation-detection&quot;&gt;Deviation Detection&lt;/h3&gt;

&lt;p&gt;After a successful publication at a valuation timestamp that meets quorum, the
non-view publication path MUST calculate:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;spread = maxNav - minNav
deviationBps = spread * 10_000 / abs(medianNav)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The calculation MUST account safely for signed values. If the spread is zero,
deviation is zero. If the median is zero while spread is nonzero, or if the
calculation would overflow, deviation MUST saturate at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(uint256).max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;deviationBps &amp;gt; deviationThresholdBps&lt;/code&gt;, the oracle MUST emit
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NAVDeviationDetected&lt;/code&gt; from the publication transaction. Equality does not
trigger the event.&lt;/p&gt;

&lt;p&gt;Deviation events are alerts. They do not invalidate submissions or prevent
aggregation.&lt;/p&gt;

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

&lt;p&gt;Compliant core oracles MUST implement &lt;a href=&quot;./eip-165.md&quot;&gt;ERC-165&lt;/a&gt; and return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(INAVSnapshotOracle).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Implementations supporting aggregation MUST also return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type(INAVAggregation).interfaceId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;ERC-165 indicates interface support only. It does not establish provider
credentials, NAV accuracy, methodology validity, liquidity, redemption rights,
or use of the oracle by a consuming contract.&lt;/p&gt;

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

&lt;h3 id=&quot;why-key-streams-by-subject-and-currency&quot;&gt;Why Key Streams by Subject and Currency?&lt;/h3&gt;

&lt;p&gt;A subject can be valued in multiple denominations. Treating each pair as an
independent stream removes ambiguity and permits separate history, staleness,
and aggregation configuration.&lt;/p&gt;

&lt;h3 id=&quot;why-configure-nav-basis-at-stream-level&quot;&gt;Why Configure NAV Basis at Stream Level?&lt;/h3&gt;

&lt;p&gt;Per-unit, per-share, and total NAV differ materially. If providers can choose
basis independently, one mismatched submission can make a quorum set
incomparable or unavailable. Immutable stream-level basis configuration rejects
the mismatch before it enters the stream.&lt;/p&gt;

&lt;h3 id=&quot;why-separate-valuation-and-publication-timestamps&quot;&gt;Why Separate Valuation and Publication Timestamps?&lt;/h3&gt;

&lt;p&gt;A value can be published recently while describing an old valuation. Consumers
need both times to assess operational feed health and economic recency.&lt;/p&gt;

&lt;h3 id=&quot;why-signed-nav&quot;&gt;Why Signed NAV?&lt;/h3&gt;

&lt;p&gt;Liabilities can exceed assets. A signed representation avoids silently
excluding insolvent or leveraged subjects, while consumers remain responsible
for handling nonpositive values safely.&lt;/p&gt;

&lt;h3 id=&quot;why-corrections&quot;&gt;Why Corrections?&lt;/h3&gt;

&lt;p&gt;Valuations can be restated after administrator error, late information, audit
adjustments, or model changes. Correction links preserve the earlier assertion
and identify its successor.&lt;/p&gt;

&lt;h3 id=&quot;why-administrative-invalidation&quot;&gt;Why Administrative Invalidation?&lt;/h3&gt;

&lt;p&gt;Correction requires the original provider. If that provider is compromised,
revoked, or unavailable, a poisoned terminal snapshot could otherwise remain
current and continue to satisfy quorum. Invalidation excludes it without
deleting history and allows a valid replacement.&lt;/p&gt;

&lt;h3 id=&quot;why-latest-by-valuation-time&quot;&gt;Why Latest by Valuation Time?&lt;/h3&gt;

&lt;p&gt;A late correction for an older valuation should not displace a more recent
valuation as the stream’s raw latest value. Period recency and publication
recency answer different questions.&lt;/p&gt;

&lt;h3 id=&quot;why-lower-median-aggregation&quot;&gt;Why Lower-Median Aggregation?&lt;/h3&gt;

&lt;p&gt;Median aggregation resists a minority of extreme submissions. Selecting the
lower median for even sets makes the result deterministic without introducing
rounding between two signed values.&lt;/p&gt;

&lt;h3 id=&quot;why-dual-staleness&quot;&gt;Why Dual Staleness?&lt;/h3&gt;

&lt;p&gt;Publication heartbeat detects a feed that stopped updating. Maximum valuation
age detects publication of economically old data. Either condition can matter
independently.&lt;/p&gt;

&lt;h3 id=&quot;prior-art&quot;&gt;Prior Art&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;./eip-4626.md&quot;&gt;ERC-4626&lt;/a&gt; defines tokenized vault accounting and conversion
functions. This ERC can provide an external valuation input but does not define
vault accounting, deposits, withdrawals, or redemption guarantees.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;./eip-7540.md&quot;&gt;ERC-7540&lt;/a&gt; extends ERC-4626 for asynchronous requests, and
&lt;a href=&quot;./eip-7575.md&quot;&gt;ERC-7575&lt;/a&gt; supports multi-asset vaults. Both may consume NAV but
do not define this provider-attributed snapshot lifecycle.&lt;/p&gt;

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

&lt;p&gt;This ERC introduces new interfaces and does not modify existing token, vault,
oracle, or accounting standards.&lt;/p&gt;

&lt;p&gt;Existing systems can deploy a companion oracle and map their asset or fund
identifier to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;subjectId&lt;/code&gt;. Integration is optional.&lt;/p&gt;

&lt;p&gt;Vault integrations should not call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAVStatus&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;aggregatedNAV&lt;/code&gt; from
critical conversion paths unless configuration is guaranteed. These functions
revert when staleness configuration is absent. Adapters can validate and cache
an accepted NAV for non-reverting preview or conversion surfaces.&lt;/p&gt;

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

&lt;p&gt;Implementations should test at least:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;stream isolation by subject and currency;&lt;/li&gt;
  &lt;li&gt;one-time known-basis configuration and publication-before-configuration
rejection;&lt;/li&gt;
  &lt;li&gt;rejection of provider basis mismatch;&lt;/li&gt;
  &lt;li&gt;signed NAV, decimal, magnitude, and future-valuation bounds;&lt;/li&gt;
  &lt;li&gt;methodology hash requirements and documented empty-URI behavior;&lt;/li&gt;
  &lt;li&gt;provider/timestamp original uniqueness;&lt;/li&gt;
  &lt;li&gt;correction provider, timestamp, basis, terminal, and latest-slot guards;&lt;/li&gt;
  &lt;li&gt;correction-of-correction chains and current-state helpers;&lt;/li&gt;
  &lt;li&gt;latest selection by valuation timestamp rather than publication order;&lt;/li&gt;
  &lt;li&gt;provider history including corrected and invalidated records;&lt;/li&gt;
  &lt;li&gt;publication and valuation staleness before, at, and after each boundary;&lt;/li&gt;
  &lt;li&gt;staleness-aware query rejection while unconfigured;&lt;/li&gt;
  &lt;li&gt;original and correction invalidation;&lt;/li&gt;
  &lt;li&gt;predecessor restoration and replacement publication after invalidation;&lt;/li&gt;
  &lt;li&gt;latest-provider, latest-stream, and quorum recomputation after invalidation;&lt;/li&gt;
  &lt;li&gt;aggregation configuration and historical quorum discovery;&lt;/li&gt;
  &lt;li&gt;provider caps and quorum limits;&lt;/li&gt;
  &lt;li&gt;decimal normalization and lower-median selection;&lt;/li&gt;
  &lt;li&gt;latest eligible valuation-timestamp selection;&lt;/li&gt;
  &lt;li&gt;provider submission pagination and ordering;&lt;/li&gt;
  &lt;li&gt;corrected and invalidated submission exclusion;&lt;/li&gt;
  &lt;li&gt;deviation threshold, zero-median, and overflow saturation behavior;&lt;/li&gt;
  &lt;li&gt;fiat and token currency derivation; and&lt;/li&gt;
  &lt;li&gt;positive and negative ERC-165 detection.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;A Solidity reference implementation, constants library, unit tests, Medusa
property tests, deployment configuration, and independent audit are linked from
the official discussion thread.&lt;/p&gt;

&lt;p&gt;The reference implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;uses provider, configurer, and administrator roles;&lt;/li&gt;
  &lt;li&gt;supports all core and aggregation functions in one contract;&lt;/li&gt;
  &lt;li&gt;caps providers per valuation timestamp at 64;&lt;/li&gt;
  &lt;li&gt;uses deterministic lower-median aggregation;&lt;/li&gt;
  &lt;li&gt;emits deviation alerts from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;publishNAV&lt;/code&gt;; and&lt;/li&gt;
  &lt;li&gt;recomputes affected indexes after administrative invalidation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role assignments and the provider cap are reference deployment choices. The
stream basis, correction, invalidation, staleness, and deterministic aggregation
semantics are requirements of this ERC.&lt;/p&gt;

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

&lt;h3 id=&quot;nav-is-not-an-executable-price&quot;&gt;NAV Is Not an Executable Price&lt;/h3&gt;

&lt;p&gt;NAV is an accounting or valuation assertion. A token can trade above or below
NAV, and redemption can be gated, delayed, limited, or unavailable. Consumers
must not treat NAV as a liquid market price without separately validating
liquidity and redemption assumptions.&lt;/p&gt;

&lt;h3 id=&quot;provider-and-configurer-trust&quot;&gt;Provider and Configurer Trust&lt;/h3&gt;

&lt;p&gt;A provider can publish fabricated or mistaken values and methodologies. A
configurer can choose unsafe staleness or quorum settings. Implementations must
document authorization, governance, upgrade, and key-management policies.&lt;/p&gt;

&lt;p&gt;Revoking a provider role does not invalidate its existing snapshots. An
authorized invalidator must separately invalidate any snapshot that should no
longer participate in current queries.&lt;/p&gt;

&lt;h3 id=&quot;methodology-verification&quot;&gt;Methodology Verification&lt;/h3&gt;

&lt;p&gt;A methodology hash is useful only when consumers can obtain the committed
document representation and reproduce the hash. An empty or unavailable URI
can make independent verification impossible unless an out-of-band retrieval
process is documented.&lt;/p&gt;

&lt;h3 id=&quot;staleness-enforcement&quot;&gt;Staleness Enforcement&lt;/h3&gt;

&lt;p&gt;Staleness flags protect only consumers that check them. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latestNAV&lt;/code&gt; deliberately
returns raw data without a staleness decision. Pricing and settlement paths
should use validated status or a controlled adapter.&lt;/p&gt;

&lt;h3 id=&quot;negative-and-zero-nav&quot;&gt;Negative and Zero NAV&lt;/h3&gt;

&lt;p&gt;Consuming contracts that assume positive NAV can underflow, divide by zero, or
misprice assets. They must define explicit behavior for zero and negative
values.&lt;/p&gt;

&lt;h3 id=&quot;provider-collusion-and-correlated-error&quot;&gt;Provider Collusion and Correlated Error&lt;/h3&gt;

&lt;p&gt;Median and quorum reduce single-provider influence but do not prevent collusion,
shared data-source failures, or common methodology errors. Address count does
not prove provider independence.&lt;/p&gt;

&lt;h3 id=&quot;invalidation-authority-and-cost&quot;&gt;Invalidation Authority and Cost&lt;/h3&gt;

&lt;p&gt;Invalidation can remove legitimate data and change latest or aggregate values.
The authority should be strongly controlled and every reason commitment should
be independently reviewable.&lt;/p&gt;

&lt;p&gt;Recomputing latest and quorum pointers can require work proportional to stream
history. Production implementations with long histories should use bounded or
checkpointed indexing while preserving the specified results.&lt;/p&gt;

&lt;h3 id=&quot;correction-and-invalidation-interpretation&quot;&gt;Correction and Invalidation Interpretation&lt;/h3&gt;

&lt;p&gt;Invalidation can detach a historical correction and permit a replacement branch.
Consumers must combine correction pointers with invalidation state and events;
following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;correctsIndex&lt;/code&gt; alone does not identify the current branch.&lt;/p&gt;

&lt;h3 id=&quot;front-running-valuation-updates&quot;&gt;Front-Running Valuation Updates&lt;/h3&gt;

&lt;p&gt;Material NAV changes visible before inclusion can enable transactions against
an older accepted value. Deployments should consider private submission,
commit-reveal publication, settlement pauses, or delayed activation when the
economic risk justifies the complexity.&lt;/p&gt;

&lt;h3 id=&quot;timestamp-dependence&quot;&gt;Timestamp Dependence&lt;/h3&gt;

&lt;p&gt;Valuation timestamps are provider assertions, and staleness uses
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block.timestamp&lt;/code&gt;. Block producers can influence timestamps within protocol
bounds. Consumers must account for this uncertainty.&lt;/p&gt;

&lt;h3 id=&quot;decimal-normalization&quot;&gt;Decimal Normalization&lt;/h3&gt;

&lt;p&gt;Aggregation multiplies lower-precision signed values. Implementations must
enforce the numeric bounds in this ERC before normalization and use checked
arithmetic.&lt;/p&gt;

&lt;h3 id=&quot;privacy-and-commercial-sensitivity&quot;&gt;Privacy and Commercial Sensitivity&lt;/h3&gt;

&lt;p&gt;Methodology URIs, valuation timing, and provider behavior can reveal sensitive
fund or asset information. Deployments should avoid publishing confidential
documents or predictable private references on public chains.&lt;/p&gt;

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

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

      </description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://ercs.ethereum.org//ERCS/erc-8330</link>
        <guid isPermaLink="true">https://ercs.ethereum.org//ERCS/erc-8330</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
  </channel>
</rss>
