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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


      </description>
        <pubDate>Sun, 18 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-1191</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-1191</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>RTA-Controlled Security Token</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #1450 - RTA-Controlled Security Token&lt;/strong&gt; is in Last Call status. It is authored by Howard Marks (@howardmarks) &lt;howard@startengine.com&gt;, Devender Gollapally (@devender-startengine) &lt;devender@startengine.com&gt;, Joe Mathews (@se-joe) &lt;joe@startengine.com&gt;, Jordan Jahja (@jordan-jahja) &lt;jordan.jahja@startengine.com&gt;, John Shiple (@johnshiple), David Zhang (@david-colab) &lt;david@startengine.com&gt; and was originally created 2018-09-25. 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-1450-rta-controlled-security-token-standard/26385&quot;&gt;https://ethereum-magicians.org/t/erc-1450-rta-controlled-security-token-standard/26385&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;abstract&quot;&gt;Abstract&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-1450&quot;&gt;ERC-1450&lt;/a&gt; facilitates the recording of ownership and transfer of securities sold in compliance with Securities Act Regulations CF, D, and A. This standard is informed by practical operational experience from SEC-registered transfer agents, broker-dealers, and alternative trading systems that have collectively managed billions in compliant securities offerings. The design addresses the full lifecycle of digital securities from issuance through secondary trading.&lt;/p&gt;

&lt;p&gt;The standard introduces a unique RTA-controlled model where the Registered Transfer Agent maintains exclusive authority over all token operations. Unlike permissionless tokens, ERC-1450 enforces strict compliance by requiring the RTA to execute all mints, burns, and transfers, while disabling direct value movement via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve()&lt;/code&gt;. Holder-initiated transfer requests are permitted via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestTransferWithFee()&lt;/code&gt;, but no value moves unless the RTA authorizes and executes the transfer. The standard also enables compliant secondary markets through a broker registration system, where vetted brokers can request transfers with fees on behalf of holders. This design ensures regulatory compliance with SEC requirements and state blue sky laws while providing liquidity options and maintaining read-only compatibility with existing &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; infrastructure.&lt;/p&gt;

&lt;p&gt;Key features include RTA-exclusive control, restricted &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; interface for ecosystem integration, and built-in mechanisms for regulatory compliance including recovery procedures for lost tokens and support for court-ordered transfers. The standard MAY optionally implement &lt;a href=&quot;/EIPS/eip-3668&quot;&gt;EIP-3668&lt;/a&gt; (CCIP-Read) for off-chain compliance pre-checks, improving user experience by allowing wallets to validate transfers before gas payment.&lt;/p&gt;

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

&lt;p&gt;With the advent of the JOBS Act in 2012 and subsequent regulations (Regulation Crowdfunding in 2016, amended Reg A and Reg D), there has been significant expansion in exemptions for securities offerings. The regulated securities market has grown substantially, with billions in offerings across thousands of companies.&lt;/p&gt;

&lt;p&gt;Experience from operating SEC-registered transfer agents has revealed critical gaps in existing token standards for securities. While standards like &lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt; provide on-chain compliance mechanisms, they don’t address the unique regulatory requirements of U.S. securities law, particularly the role of Registered Transfer Agents.&lt;/p&gt;

&lt;p&gt;Current challenges that ERC-1450 addresses:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Transfer Controller Authority&lt;/strong&gt;: SEC regulations require Registered Transfer Agents to maintain exclusive control over securities transfers, similar to designated controller requirements in other jurisdictions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Recovery Mechanisms&lt;/strong&gt;: Legal requirements for recovering lost or stolen securities&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Court Orders&lt;/strong&gt;: Ability to execute court-ordered transfers (divorce, estate, fraud recovery)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Reporting&lt;/strong&gt;: Clear audit trails for regulatory examinations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cost Efficiency&lt;/strong&gt;: Leveraging existing transfer agent infrastructure for compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ERC-20 tokens do not support the regulated roles of Funding Portal, Broker Dealer, RTA, and Investor and do not support the Bank Secrecy Act/USA Patriot Act KYC and AML requirements. Other improvements (notably Simple Restricted Token Standards) have tried to tackle KYC and AML regulatory requirements. This approach assigns exclusive control over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burnFrom&lt;/code&gt; to a designated transfer agent who performs KYC and AML compliance.&lt;/p&gt;

&lt;p&gt;This standard codifies operational requirements into a technical specification that bridges traditional securities regulation with blockchain technology.&lt;/p&gt;

&lt;h2 id=&quot;specification&quot;&gt;Specification&lt;/h2&gt;
&lt;p&gt;ERC-1450 extends &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;optional-dependencies&quot;&gt;Optional Dependencies&lt;/h3&gt;
&lt;p&gt;The following standards MAY be implemented for enhanced functionality but are NOT required for compliance:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-3668&quot;&gt;EIP-3668 (CCIP-Read)&lt;/a&gt;&lt;/strong&gt;: MAY be used for off-chain compliance pre-checks. Implementations choosing to support this MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preCheckCompliance&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preCheckComplianceCallback&lt;/code&gt; functions as specified.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;/EIPS/eip-1820&quot;&gt;ERC-1820 (Registry)&lt;/a&gt;&lt;/strong&gt;: MAY be used for interface registration. Implementations can optionally register their interfaces in the ERC-1820 registry for improved discoverability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to the optional standards above, the following interface components defined in this specification are OPTIONAL extensions. Implementations MAY omit them; implementations that provide them MUST follow the behavior specified for them (including emitting the specified events):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Document management&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAllDocuments&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Structured recovery workflow&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initiateRecovery&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cancelRecovery&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;executeRecovery&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecoveryDetails&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hasPendingRecovery&lt;/code&gt;) — the REQUIRED baseline for lost-wallet recovery and court-ordered transfers is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;controllerTransfer&lt;/code&gt;, which all implementations MUST provide&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;KYC status view&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isKYCVerified&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gasless fee approval&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestTransferWithPermit&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Off-chain compliance pre-checks&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preCheckCompliance&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preCheckComplianceCallback&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transfer request status view&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRequestStatus&lt;/code&gt;) — implementations MAY instead expose equivalent request data through other read methods (e.g., a public storage mapping)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;erc-1450&quot;&gt;ERC-1450&lt;/h3&gt;
&lt;p&gt;ERC-1450 is an interface standard that defines a security token where only the Registered Transfer Agent (RTA) has authority to execute transfers, mints, and burns. The token represents securities issued by an owner (the issuer) and managed exclusively by an RTA.&lt;/p&gt;

&lt;p&gt;The standard enforces strict role separation:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Owner/Issuer&lt;/strong&gt;: The entity that creates and owns the security&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RTA&lt;/strong&gt;: The only entity authorized to transfer, mint, or burn tokens&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Token Holders&lt;/strong&gt;: Cannot initiate transfers directly (unlike standard &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ERC-1450 explicitly disables direct value movement by requiring the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve&lt;/code&gt; functions to always revert. Only the RTA can execute token movements via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burnFrom&lt;/code&gt; functions. Holder-initiated transfer requests are permitted via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestTransferWithFee()&lt;/code&gt;, but no value moves unless the RTA authorizes and executes the transfer. Registered brokers can also request transfers on behalf of holders through the same mechanism. This design ensures regulatory compliance by centralizing all token operations through the regulated RTA.&lt;/p&gt;

&lt;p&gt;Critical security feature: The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeIssuer&lt;/code&gt; function can only be called by the RTA, not the owner. This protects against compromised issuer keys - even if an issuer’s private key is stolen, the attacker cannot change the RTA or steal tokens.&lt;/p&gt;

&lt;h3 id=&quot;issuers-and-rtas&quot;&gt;Issuers and RTAs&lt;/h3&gt;
&lt;p&gt;Implementations must initialize the following parameters upon deployment:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;owner&lt;/code&gt;: The issuer’s address&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferAgent&lt;/code&gt;: The RTA’s address (preferably an RTAProxy contract)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name&lt;/code&gt;: The security’s name&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol&lt;/code&gt;: The security’s trading symbol&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals&lt;/code&gt;: The number of decimal places (0 for indivisible shares, up to 18 for fractional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;access-control-model&quot;&gt;Access Control Model&lt;/h4&gt;
&lt;p&gt;The interface defines three levels of access control:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RTA-Only Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeIssuer&lt;/code&gt;: Change the token issuer/owner (only callable by RTA, not by issuer)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;: Transfer tokens between accounts&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;: Create new tokens&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burnFrom&lt;/code&gt;: Destroy existing tokens&lt;/li&gt;
  &lt;li&gt;All batch operations and fee collection functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Owner-Only Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTransferAgent&lt;/code&gt;: One-time setup to RTAProxy (locked after initial setup)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Public Functions:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isTransferAgent&lt;/code&gt;: Check if an address is the current RTA&lt;/li&gt;
  &lt;li&gt;Standard &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; view functions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balanceOf&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalSupply&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;security-and-compliance&quot;&gt;Security and Compliance&lt;/h4&gt;
&lt;p&gt;The RTA maintains exclusive control over all token movements, ensuring:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Complete audit trail for regulatory reporting&lt;/li&gt;
  &lt;li&gt;Enforcement of transfer restrictions&lt;/li&gt;
  &lt;li&gt;Recovery mechanisms for lost tokens&lt;/li&gt;
  &lt;li&gt;Execution of court orders&lt;/li&gt;
  &lt;li&gt;Prevention of unauthorized transfers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;erc-20-extension&quot;&gt;&lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; Extension&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; tokens provide the following functionality:&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: MIT
&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;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;IERC20&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;totalSupply&lt;/span&gt;&lt;span class=&quot;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;balanceOf&lt;/span&gt;&lt;span class=&quot;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;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;nb&quot;&gt;transfer&lt;/span&gt;&lt;span class=&quot;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;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;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;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;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;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;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;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;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;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;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;spender&lt;/span&gt;&lt;span class=&quot;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;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;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Transfer&lt;/span&gt;&lt;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;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;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;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;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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; interface for standard interface detection:&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: MIT
&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;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;IERC165&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Query if a contract implements an interface
     * @param interfaceId The interface identifier, as specified in [ERC-165](/EIPS/eip-165)
     * @return bool True if the contract implements `interfaceId`
     */&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;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;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt; is extended 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;c1&quot;&gt;// SPDX-License-Identifier: MIT
&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;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * @title ERC-1450: RTA-Controlled Security Token (Restricted ERC-20 Interface)
 * @notice Facilitates compliance with Securities Act Regulations CF, D, and A
 * @dev This standard extends ERC-20 with RTA-controlled transfer restrictions
 *
 * Key Features:
 * - RTA (Registered Transfer Agent) exclusive control over transfers
 * - Direct value movement disabled (transfer, approve functions always revert)
 * - Holder-initiated transfer requests permitted via requestTransferWithFee (requires RTA execution)
 * - Built-in recovery mechanisms for lost tokens
 * - Support for court-ordered transfers
 * - Restricted ERC-20 interface for read operations and ecosystem integration
 * - ERC-6093 compliant error messages for tooling interoperability
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1450&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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;c1&quot;&gt;// ============ ERC-6093 Standard Errors ============
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Using standard errors from ERC-6093 for consistent tooling support
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Standard ERC-20 errors (from ERC-6093)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC20InsufficientBalance&lt;/span&gt;&lt;span class=&quot;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;nb&quot;&gt;balance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;needed&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;ERC20InvalidSender&lt;/span&gt;&lt;span class=&quot;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;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC20InvalidReceiver&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver&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;ERC20InvalidApprover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;approver&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;ERC20InvalidSpender&lt;/span&gt;&lt;span class=&quot;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;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC20InsufficientAllowance&lt;/span&gt;&lt;span class=&quot;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;uint256&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;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;needed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Standard Access Control errors (from ERC-6093)
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// NOTE: We retain OpenZeppelin error names for tooling compatibility, but semantics differ:
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// - &quot;Owner&quot; in ERC-1450 means &quot;Issuer&quot; (the entity that created the token)
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// - Unlike OpenZeppelin&apos;s Ownable, only the RTA can change the issuer, not the issuer themselves
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OwnableUnauthorizedAccount&lt;/span&gt;&lt;span class=&quot;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;c1&quot;&gt;// Non-issuer attempts issuer-only operation
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OwnableInvalidOwner&lt;/span&gt;&lt;span class=&quot;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;c1&quot;&gt;// Invalid issuer address (e.g., zero address)
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ============ ERC-1450 Specific Errors ============
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Custom errors only when ERC-6093 standard errors are insufficient
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC1450TransferDisabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// For disabled transfer/approve functions
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC1450OnlyRTA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Operation restricted to RTA only
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC1450TransferAgentLocked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// RTA proxy is locked from changes
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERC1450ComplianceCheckFailed&lt;/span&gt;&lt;span class=&quot;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;// KYC/AML failure
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Events
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IssuerChanged&lt;/span&gt;&lt;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;previousIssuer&lt;/span&gt;&lt;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;newIssuer&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;TransferAgentUpdated&lt;/span&gt;&lt;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;previousAgent&lt;/span&gt;&lt;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;newAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Emitted when tokens are minted with regulation tracking
     * @param to Recipient of the minted tokens
     * @param amount Number of tokens minted
     * @param regulationType Regulation under which tokens were issued
     * @param issuanceDate Original share issuance date
     * @param tokenizationDate When tokenized on blockchain (block.timestamp)
     * @dev MUST be emitted for every mint operation
     *      Allows reconstruction of entire cap table from events
     *      Critical for regulatory reporting and audit trails
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokensMinted&lt;/span&gt;&lt;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;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tokenizationDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Emitted when tokens are burned with regulation tracking
     * @param from Address from which tokens were burned
     * @param amount Number of tokens burned
     * @param regulationType Regulation type of burned tokens
     * @param issuanceDate Original issuance date of burned tokens
     * @dev MUST be emitted for every burn operation
     *      Critical for maintaining accurate cap table and regulatory reporting
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TokensBurned&lt;/span&gt;&lt;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;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Emitted when tokens are transferred with specific regulation tracking
     * @param from Source address
     * @param to Destination address
     * @param amount Number of tokens transferred
     * @param regulationType Regulation type of the transferred tokens
     * @param issuanceDate Original issuance date of the transferred tokens
     * @dev Provides complete traceability of regulated token movements
     *      Essential for compliance reporting and audit trails
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RegulatedTransfer&lt;/span&gt;&lt;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;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Core RTA Functions
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Change the issuer (owner) of the token contract
     * @param newIssuer Address of the new issuer
     * @dev Only callable by the RTA. Must be restricted with onlyTransferAgent modifier.
     *      Emits IssuerChanged event (not OwnershipTransferred)
     *
     *      IMPORTANT: This differs from OpenZeppelin&apos;s Ownable pattern:
     *      - In Ownable: owner can transfer ownership themselves
     *      - In ERC-1450: ONLY the RTA can change the issuer
     *      - Terminology: &quot;Issuer&quot; = the token creator/owner, not the controller
     *      - This prevents compromised issuer keys from hijacking the token
     *
     *      The issuer maintains rights to:
     *      - Receive proceeds from offerings
     *      - Update corporate documents (via ERC-1643)
     *      - Make business decisions
     *      But CANNOT control token transfers or change the RTA
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;changeIssuer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newIssuer&lt;/span&gt;&lt;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 Update the transfer agent address (one-time use or RTA-only after initial setup)
     * @param newTransferAgent Address of the new transfer agent (should be RTAProxy contract)
     * @dev After initial setup to RTAProxy, only the RTA can rotate itself via the proxy.
     *      This prevents compromised issuers from changing the RTA.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setTransferAgent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTransferAgent&lt;/span&gt;&lt;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 Check if an address is the current transfer agent
     * @param account Address to check
     * @return bool True if the address is the current transfer agent
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isTransferAgent&lt;/span&gt;&lt;span class=&quot;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;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;c1&quot;&gt;// ERC-20 Overrides (Restricted Functions)
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Transfer tokens - DISABLED for security tokens
     * @dev Must always revert with ERC1450TransferDisabled()
     *      Uses specific error for disabled functionality per [ERC-6093](/EIPS/eip-6093) guidelines
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;transfer&lt;/span&gt;&lt;span class=&quot;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;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;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;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Approve spending - DISABLED for security tokens
     * @dev Must always revert with ERC1450TransferDisabled()
     *      Uses specific error for disabled functionality per [ERC-6093](/EIPS/eip-6093) guidelines
     */&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;spender&lt;/span&gt;&lt;span class=&quot;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;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;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get spending allowance - DISABLED for security tokens
     * @dev Must always return 0
     */&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;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;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;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Transfer tokens - DISABLED for security tokens
     * @dev Must always revert with ERC1450TransferDisabled()
     *      Uses specific error for disabled functionality per [ERC-6093](/EIPS/eip-6093) guidelines
     *      Use transferFromRegulated() for actual transfers with regulation tracking
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&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;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;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;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;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// RTA-Controlled Functions
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Transfer tokens between accounts with regulation tracking (RTA only)
     * @param from Source address
     * @param to Destination address
     * @param amount Number of tokens to transfer
     * @param regulationType Type of regulation for the transferred tokens
     * @param issuanceDate Original issuance date of the transferred tokens
     * @dev Only callable by the registered transfer agent
     *      The regulation type and issuance date specify which tokens to transfer
     *      MUST revert if sender has insufficient tokens of the specified regulation/issuance
     *      Callers SHOULD first check holdings via getHolderRegulations() or getDetailedBatchInfo()
     *      This enables precise control over which token batches are moved
     *      The RTA determines the transfer strategy (FIFO, LIFO, tax optimization, etc.)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;transferFromRegulated&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;&lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Mint new tokens with regulation tracking (RTA only)
     * @param to Address to receive the minted tokens
     * @param amount Number of tokens to mint
     * @param regulationType Type of regulation under which shares were issued (uint16 for global compatibility)
     * @param issuanceDate Unix timestamp when shares were originally issued (not tokenization date)
     * @dev Only callable by the registered transfer agent
     *      Every security MUST specify a regulation type - there are no &quot;unregulated&quot; securities
     *      For tokenizing existing securities, issuanceDate should be when investor originally purchased
     *      For new issuances, issuanceDate would typically be block.timestamp
     *      RTA uses issuanceDate to calculate holding periods for regulatory compliance
     */&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;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;&lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Batch mint tokens with regulation tracking (RTA only)
     * @param recipients Array of addresses to receive the minted tokens
     * @param amounts Array of token amounts to mint for each recipient
     * @param regulationTypes Array of regulation types for each mint
     * @param issuanceDates Array of issuance timestamps for each mint
     * @dev Only callable by the registered transfer agent
     *      All arrays MUST be the same length
     *      Each mint operation follows the same rules as individual mint()
     *      Reverts if any single mint would fail
     *      Emits TokensMinted event for each successful mint
     *      Enables efficient bulk issuance while maintaining compliance tracking
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batchMint&lt;/span&gt;&lt;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;recipients&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amounts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&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;regulationTypes&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDates&lt;/span&gt;
    &lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Burn tokens from an account (RTA only) - Uses RTA&apos;s chosen strategy
     * @param from Address from which to burn tokens
     * @param amount Number of tokens to burn
     * @dev Only callable by the registered transfer agent
     *      The RTA determines which tokens to burn based on their strategy (FIFO, LIFO, tax optimization, etc.)
     *      Use burnFromRegulated() to burn specific regulation/issuance tokens
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;burnFrom&lt;/span&gt;&lt;span class=&quot;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;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;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 Burn tokens from an account with regulation tracking (RTA only)
     * @param from Address from which to burn tokens
     * @param amount Number of tokens to burn
     * @param regulationType Type of regulation for the tokens to burn
     * @param issuanceDate Original issuance date of the tokens to burn
     * @dev Only callable by the registered transfer agent
     *      Burns specific tokens identified by regulation type and issuance date
     *      MUST revert if holder has insufficient tokens of the specified regulation/issuance
     *      Callers SHOULD first check holdings via getHolderRegulations() or getDetailedBatchInfo()
     *      MUST emit TokensBurned event with the specific regulation details
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;burnFromRegulated&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;&lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Burn tokens of a specific regulation type (RTA only)
     * @param from Address from which to burn tokens
     * @param amount Number of tokens to burn
     * @param regulationType Specific regulation type to burn
     * @dev Only callable by the registered transfer agent
     *      Useful for partial redemptions, buybacks, or regulation-specific corporate actions
     *      Reverts if holder has insufficient tokens of the specified regulation type
     *      MUST emit TokensBurned event with the specific regulation details
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;burnFromRegulation&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Get token decimals (OPTIONAL per [EIP-20](/EIPS/eip-20))
     * @return uint8 The number of decimal places (0-18)
     * @dev Set at deployment based on security type:
     *      - 0 for traditional indivisible shares
     *      - Greater than 0 for fractional shares (mutual funds, REITs, fractional trading)
     *      - Must be immutable after deployment
     *
     *      NOTE: Per [EIP-20](/EIPS/eip-20), name(), symbol(), and decimals() are OPTIONAL
     *      Implementations SHOULD provide these for better UX
     *      Wallets MUST NOT assume these functions exist
     */&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;c1&quot;&gt;// Introspection for Restricted ERC-20 Interface Detection
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Check if this is a security token with restricted transfers
     * @return bool Always returns true for ERC-1450 tokens
     * @dev Critical for wallets/DEXs to detect restricted tokens and handle appropriately.
     *      Prevents users from attempting transfers that will always fail.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSecurityToken&lt;/span&gt;&lt;span class=&quot;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;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Returns the contract implementation version
     * @return string Semantic version string (e.g., &quot;1.17.0&quot;)
     * @dev Enables upgrade detection for UUPS-upgradeable contracts.
     *      Version SHOULD match the reference implementation package version.
     *      Useful for:
     *      - Detecting available upgrades by comparing deployed vs local version
     *      - Audit trails showing which version was deployed
     *      - Debugging and support by identifying exact implementation
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;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;k&quot;&gt;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice [EIP-165](/EIPS/eip-165) support for interface detection
     * @param interfaceId The interface identifier to check
     * @return bool True if the contract implements the interface
     * @dev MUST return true for:
     *      - 0x01ffc9a7: [ERC-165](/EIPS/eip-165) interface ID
     *      - 0xXXXXXXXX: IERC1450 interface ID (see Interface Detection section for calculation)
     *
     *      MUST return false for:
     *      - 0x36372b07: [ERC-20](/EIPS/eip-20) interface ID
     *
     *      Returning false for [ERC-20](/EIPS/eip-20) prevents wallets from assuming standard transfer behavior.
     *      While we are ABI-compatible with [ERC-20](/EIPS/eip-20), we are not behaviorally compatible
     *      since transfer() and approve() always revert.
     */&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;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;c1&quot;&gt;// KYC/AML Status Check (OPTIONAL)
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Check if an address has been KYC verified (OPTIONAL)
     * @param account Address to check
     * @return verified Whether the address is linked to a verified person
     * @return expiryDate When the KYC verification expires (0 if not verified)
     * @dev This is a view function that queries the RTA&apos;s off-chain database
     *      Never returns actual identity information, only verification status
     *      Implementations MAY choose to implement this for transparency
     *      Returns false for addresses that have never been verified
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isKYCVerified&lt;/span&gt;&lt;span class=&quot;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;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;n&quot;&gt;verified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiryDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Regulation Tracking Query Functions
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get regulation information for tokens held by an address
     * @param holder Address to query
     * @return regulationTypes Array of regulation types for holder&apos;s tokens
     * @return amounts Array of token amounts per regulation type
     * @return issuanceDates Array of original issuance dates
     * @dev MUST return arrays of equal length representing holder&apos;s token composition
     *      Implementation MUST store this data persistently on-chain
     *      RTA uses this for transfer calculations and compliance checks
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHolderRegulations&lt;/span&gt;&lt;span class=&quot;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;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;uint16&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;regulationTypes&lt;/span&gt;&lt;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;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amounts&lt;/span&gt;&lt;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;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDates&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get total tokens minted under a specific regulation
     * @param regulationType The regulation type to query
     * @return totalSupply Total tokens minted under this regulation
     * @dev Useful for regulatory reporting and tracking offering limits
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRegulationSupply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;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;totalSupply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get detailed batch information for a holder&apos;s tokens
     * @param holder Address to query
     * @return count Number of unique batches the holder has
     * @return regulationTypes Array of regulation types for each batch
     * @return issuanceDates Array of issuance dates for each batch
     * @return amounts Array of token amounts for each batch
     * @dev Returns comprehensive batch-level details for a holder
     *      Useful for detailed cap table management and regulatory reporting
     *      Each index represents a unique batch of tokens with specific regulation/issuance
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getDetailedBatchInfo&lt;/span&gt;&lt;span class=&quot;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;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;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&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;regulationTypes&lt;/span&gt;&lt;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;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDates&lt;/span&gt;&lt;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;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amounts&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Batch Operations for Gas Efficiency
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Batch transfer tokens between multiple address pairs with regulation tracking (RTA only)
     * @param froms Array of source addresses
     * @param tos Array of destination addresses
     * @param amounts Array of token amounts to transfer
     * @param regulationTypes Array of regulation types for each transfer
     * @param issuanceDates Array of issuance dates for each transfer
     * @return bool True if all transfers succeed
     * @dev All arrays must have equal length. Reverts if any transfer fails.
     *      Only callable by the registered transfer agent.
     *      MUST revert if any sender has insufficient tokens of the specified regulation/issuance
     *      The RTA determines the transfer strategy for each transfer
     *      Useful for dividend distributions, corporate actions, etc.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batchTransferFrom&lt;/span&gt;&lt;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;froms&lt;/span&gt;&lt;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;tos&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amounts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&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;regulationTypes&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDates&lt;/span&gt;
    &lt;span class=&quot;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;cm&quot;&gt;/**
     * @notice Batch burn tokens from multiple addresses with regulation tracking (RTA only)
     * @param froms Array of addresses from which to burn tokens
     * @param amounts Array of token amounts to burn from each address
     * @param regulationTypes Array of regulation types for each burn
     * @param issuanceDates Array of issuance dates for each burn
     * @return bool True if all burns succeed
     * @dev All arrays must have equal length. Reverts if any burn fails.
     *      Only callable by the registered transfer agent.
     *      MUST revert if any holder has insufficient tokens of the specified regulation/issuance
     *      Useful for redemptions, corporate buybacks, etc.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batchBurnFrom&lt;/span&gt;&lt;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;froms&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amounts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&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;regulationTypes&lt;/span&gt;&lt;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;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDates&lt;/span&gt;
    &lt;span class=&quot;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;c1&quot;&gt;// Fee Collection Mechanism
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Register or deregister a broker for this token (RTA only)
     * @param broker Address of the broker to register/deregister
     * @param isApproved Whether to approve or revoke broker status
     * @dev Only callable by RTA after due diligence. Brokers must:
     *      1. Apply off-chain to the RTA
     *      2. Pass KYC/AML and regulatory checks
     *      3. Sign broker agreement
     *      4. Be approved by RTA compliance team
     *
     *      RECOMMENDED: Brokers SHOULD use a proxy pattern similar to RTAProxy
     *      for key management and operational security. This allows:
     *      - Secure key rotation without re-registration
     *      - Multi-signature controls for broker operations
     *      - Business continuity during personnel changes
     *      - Protection against individual key compromise
     *
     *      The broker address registered here MAY be:
     *      - Direct broker-controlled address (simple but less secure)
     *      - BrokerProxy contract address (recommended for production)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setBrokerStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;broker&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;isApproved&lt;/span&gt;&lt;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 Check if an address is a registered broker
     * @param broker Address to check
     * @return bool True if the address is an approved broker
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isRegisteredBroker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;broker&lt;/span&gt;&lt;span class=&quot;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 Request a transfer with fee payment
     * @param from Source address for the transfer
     * @param to Destination address for the transfer
     * @param amount Number of tokens to transfer
     * @param feeAmount Amount of fee being paid (in the configured fee token)
     * @return requestId Unique identifier for this request (for idempotency and tracking)
     * @dev Creates a new transfer request with initial status: RequestStatus.Requested
     *
     *      Fee payment:
     *      - Fee MUST be paid in the configured fee token (see getFeeToken())
     *      - Caller MUST have approved the token contract to spend feeAmount
     *      - Fee is transferred via safeTransferFrom from msg.sender
     *
     *      Fee payment responsibility:
     *      - Holder-initiated (msg.sender == from): Holder pays the fee
     *      - Broker-initiated (msg.sender != from): Broker pays fee on behalf of client
     *      - Settlement failures: Fees are NOT automatically refunded (RTA discretion)
     *
     *      Request lifecycle:
     *      1. Request created with unique requestId (status: Requested)
     *      2. RTA reviews request (status: UnderReview - optional)
     *      3. RTA approves/rejects (status: Approved or Rejected)
     *      4. If approved, RTA executes transfer (status: Executed)
     *      5. Optional: Request expires after timeout (status: Expired)
     *
     *      Idempotency guarantee:
     *      - Each requestId is unique and can only be executed ONCE
     *      - Duplicate execution attempts MUST revert
     *      - Clients can safely retry requests with new requestId if needed
     *
     *      Authorization requirements:
     *      - If msg.sender == from: Token holder requesting their own transfer
     *      - If msg.sender != from: Must be a registered broker (via setBrokerStatus)
     *      - Reverts if neither condition is met
     *
     *      Implementation MUST:
     *      - Verify fee token is configured (revert if not)
     *      - Generate unique requestId for each request
     *      - Emit TransferRequested event
     *      - Store request details for later processing
     *      - Prevent double-spending by tracking request status
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestTransferWithFee&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeAmount&lt;/span&gt;
    &lt;span class=&quot;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;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Request transfer with [EIP-2612](/EIPS/eip-2612) permit for gasless fee approval (OPTIONAL)
     * @param from Source address for the transfer
     * @param to Destination address for the transfer
     * @param amount Number of tokens to transfer
     * @param feeAmount Amount of fee being paid (in the configured fee token)
     * @param deadline Permit signature deadline
     * @param v ECDSA signature v parameter
     * @param r ECDSA signature r parameter
     * @param s ECDSA signature s parameter
     * @return requestId Unique identifier for this transfer request
     * @dev OPTIONAL: Allows fee payment without prior approve() transaction
     *      Uses [EIP-2612](/EIPS/eip-2612) permit for gasless approval of fee token
     *      Particularly useful for first-time users who don&apos;t have fee token approvals
     *      MUST revert if the configured fee token doesn&apos;t support [EIP-2612](/EIPS/eip-2612)
     *      Example: USDC, DAI, and other modern stablecoins support permit
     *
     *      Implementation:
     *      1. Call permit on the configured fee token with the provided signature
     *      2. Then execute the same logic as requestTransferWithFee
     *      3. This avoids users needing a separate approve transaction for fees
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestTransferWithPermit&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deadline&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;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
    &lt;span class=&quot;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;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get current fee for a transfer
     * @param from Source address
     * @param to Destination address
     * @param amount Transfer amount
     * @return feeAmount Required fee amount in the configured fee token
     * @dev Allows dynamic fee calculation based on transfer parameters
     *      Fee is always denominated in the configured fee token (see getFeeToken())
     *      Fee type determines calculation:
     *      - Type 0 (flat): Returns feeValue directly
     *      - Type 1 (percentage): Returns (amount * feeValue) / 10000
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getTransferFee&lt;/span&gt;&lt;span class=&quot;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;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;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;feeAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get the configured fee token address
     * @return token The [ERC-20](/EIPS/eip-20) token used for fee payments
     * @dev Returns address(0) if no fee token is configured yet
     *      RTA MUST configure a fee token before transfers can be requested
     *      Common choices: USDC, USDT, or other stablecoins
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFeeToken&lt;/span&gt;&lt;span class=&quot;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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Set the fee token (RTA only)
     * @param newFeeToken Address of the [ERC-20](/EIPS/eip-20) token to use for fees
     * @dev Only callable by RTA to configure or change the fee token
     *      MUST emit FeeTokenUpdated event
     *      MUST NOT accept address(0) - use a stablecoin like USDC
     *      Changing fee token does not affect pending transfer requests
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setFeeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newFeeToken&lt;/span&gt;&lt;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 Set fee parameters (RTA only)
     * @param feeType Type of fee structure (0: flat, 1: percentage in basis points)
     * @param feeValue Fee amount or percentage basis points
     * @dev Only callable by RTA to update fee structure
     *      MUST emit FeeParametersUpdated event
     *      For percentage fees, feeValue is in basis points (100 = 1%)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setFeeParameters&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;feeType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeValue&lt;/span&gt;&lt;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 Withdraw collected fees (RTA only)
     * @param amount Amount to withdraw (in the configured fee token)
     * @param recipient Recipient address for fees
     * @dev Only callable by RTA to collect accumulated fees
     *      Withdraws from the configured fee token balance
     *      MUST revert if insufficient collected fees
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withdrawFees&lt;/span&gt;&lt;span class=&quot;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;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipient&lt;/span&gt;&lt;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 Process pending transfer request (RTA only)
     * @param requestId ID of the transfer request
     * @param approved Whether to approve or reject the transfer
     * @dev RTA reviews and processes transfer requests after compliance checks
     *      MUST transition request through proper lifecycle states
     *      MUST emit events for each state transition
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processTransferRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestId&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;approved&lt;/span&gt;&lt;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 Reject transfer request with specific reason code (RTA only)
     * @param requestId ID of the transfer request to reject
     * @param reasonCode Rejection reason code (see Reason Codes section)
     * @param refundFee Whether to refund the fee to the requester
     * @dev Convenience function for rejections with detailed reason tracking
     *      MUST transition request status to Rejected
     *      MUST emit TransferRejected event with reasonCode and refundFee flag
     *      If refundFee is true, MUST return the fee to the original payer
     *      Alternative to processTransferRequest(requestId, false) with more detail
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rejectTransferRequest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonCode&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;refundFee&lt;/span&gt;&lt;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;// Transfer Request Lifecycle Management
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Request lifecycle states
     * @dev Requests MUST follow this state machine:
     *      Requested → UnderReview → (Approved | Rejected) → Executed
     *
     *      State transitions:
     *      - Requested: Initial state when requestTransferWithFee is called
     *      - UnderReview: RTA begins compliance checks (optional intermediate state)
     *      - Approved: RTA approves after compliance checks pass
     *      - Rejected: RTA rejects for compliance or other reasons
     *      - Executed: Transfer completed and tokens moved
     *      - Expired: Request timed out without processing (if timeouts implemented)
     *
     *      Idempotency: Each requestId MUST be unique and can only be executed ONCE
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestStatus&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Requested&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// 0: Initial state
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;UnderReview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// 1: RTA is reviewing
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;Approved&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// 2: Approved, awaiting execution
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;Rejected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// 3: Rejected, terminal state
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;Executed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// 4: Successfully executed, terminal state
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;Expired&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// 5: Timed out, terminal state
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get current status of a transfer request (OPTIONAL)
     * @param requestId The transfer request ID
     * @dev OPTIONAL: Implementations MAY instead expose equivalent request data
     *      through other read methods (e.g., a public storage mapping).
     * @return status Current RequestStatus
     * @return from Source address
     * @return to Destination address
     * @return amount Transfer amount
     * @return requestedAt Timestamp when request was created
     * @return processedAt Timestamp when request was processed (0 if pending)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRequestStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestId&lt;/span&gt;&lt;span class=&quot;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;RequestStatus&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestedAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;processedAt&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Update request status (RTA only)
     * @param requestId The transfer request ID
     * @param newStatus New status to transition to
     * @dev MUST validate state transitions according to lifecycle rules
     *      MUST emit RequestStatusChanged event
     *      Invalid transitions MUST revert
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateRequestStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RequestStatus&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newStatus&lt;/span&gt;&lt;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;// Events for transfer request lifecycle
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransferRequested&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;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;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feePaid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestedBy&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// holder or broker
&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;RequestStatusChanged&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;RequestStatus&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;RequestStatus&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&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;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransferExecuted&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;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;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;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransferRejected&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Gas-efficient reason codes (see Reason Codes section)
&lt;/span&gt;        &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeRefunded&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Whether fee was refunded
&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;TransferExpired&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expiredAt&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Fee-related events
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FeeParametersUpdated&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;feeType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeValue&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;FeeTokenUpdated&lt;/span&gt;&lt;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;previousToken&lt;/span&gt;&lt;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;newToken&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;FeesWithdrawn&lt;/span&gt;&lt;span class=&quot;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;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;recipient&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;BrokerStatusUpdated&lt;/span&gt;&lt;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;broker&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;isApproved&lt;/span&gt;&lt;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;updatedBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Account restriction events
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AccountFrozen&lt;/span&gt;&lt;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;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frozen&lt;/span&gt;&lt;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;frozenBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Reason Codes for Transfer Rejection
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Gas-efficient uint16 codes instead of strings
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_COMPLIANCE_FAILED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// KYC/AML check failed
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_INSUFFICIENT_BALANCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// Sender lacks tokens
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_RESTRICTED_ACCOUNT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// Account is frozen/restricted
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_TRANSFER_WINDOW_CLOSED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// Outside allowed transfer window
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_EXCEEDS_HOLDING_LIMIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Would exceed max holding
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_REGULATORY_HALT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// Trading halted by regulator
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_COURT_ORDER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;              &lt;span class=&quot;c1&quot;&gt;// Blocked by court order
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_INVALID_RECIPIENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Recipient not whitelisted
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_LOCK_PERIOD&lt;/span&gt; &lt;span class=&quot;o&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;c1&quot;&gt;// Tokens are locked
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_RECIPIENT_NOT_VERIFIED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Recipient hasn&apos;t completed KYC/AML
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_ADDRESS_NOT_LINKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;      &lt;span class=&quot;c1&quot;&gt;// Address not linked to verified identity
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_SENDER_VERIFICATION_EXPIRED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Sender&apos;s KYC expired
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_JURISDICTION_BLOCKED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Recipient in restricted jurisdiction
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_ACCREDITATION_REQUIRED&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Recipient not accredited (Reg D)
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_OTHER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;999&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;// Other/unspecified reason
&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Fee Refund Policy
&lt;/span&gt;    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Fee refund policy for rejected/expired transfers
     * @dev Implementations MUST clearly document their refund policy:
     *      Option 1: AUTO_REFUND - Fees automatically refunded on rejection/expiry
     *      Option 2: NO_REFUND - Fees retained for processing costs
     *      Option 3: CONDITIONAL_REFUND - Refund based on reason code
     *
     *      The refund policy SHOULD be:
     *      - Clearly documented in the contract
     *      - Communicated to users before fee payment
     *      - Consistently applied across all transfers
     *      - Emit TransferRejected event with feeRefunded flag
     */&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Optional: Off-chain Compliance Pre-check (EIP-3668 CCIP-Read)
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Pre-check transfer compliance off-chain (OPTIONAL)
     * @param from Source address for the transfer
     * @param to Destination address for the transfer
     * @param amount Number of tokens to transfer
     * @return bool True if transfer would likely pass compliance
     * @dev OPTIONAL: Implements EIP-3668 (CCIP-Read) for off-chain compliance checks
     *
     *      This check SHOULD verify:
     *      1. Sender KYC/AML status is current (not expired)
     *      2. Recipient has passed KYC/AML verification
     *      3. Recipient address ownership is verified and linked to identity
     *      4. Transfer doesn&apos;t violate jurisdiction restrictions
     *      5. Accreditation requirements are met (if applicable for Reg D/Reg A)
     *
     *      This function MAY revert with OffchainLookup error containing:
     *      - URLs for off-chain compliance services
     *      - Callback function to process off-chain response
     *
     *      Purpose: Allow wallets to pre-screen transfers before users pay gas
     *      Benefits:
     *      - Show specific compliance failure reasons upfront
     *      - Improve UX by preventing failed transactions
     *      - Reduce wasted gas on non-compliant transfers
     *
     *      IMPORTANT: This check is ADVISORY ONLY and NOT BINDING
     *      - The actual transfer still requires RTA approval
     *      - Compliance status may change between pre-check and execution
     *      - RTA has final authority on all transfers
     *
     *      Example implementation:
     *      ```solidity
     *      error OffchainLookup(address sender, string[] urls, bytes callData,
     *                          bytes4 callbackFunction, bytes extraData);
     *
     *      function preCheckCompliance(address from, address to, uint256 amount)
     *          external view returns (bool) {
     *          revert OffchainLookup(
     *              address(this),
     *              urls,  // RTA&apos;s compliance API endpoints
     *              abi.encodeWithSignature(&quot;checkCompliance(address,address,uint256)&quot;, from, to, amount),
     *              this.preCheckComplianceCallback.selector,
     *              &quot;&quot;
     *          );
     *      }
     *      ```
     *
     *      Wallets supporting [EIP-3668](/EIPS/eip-3668) will:
     *      1. Catch the OffchainLookup error
     *      2. Query the specified URLs with the provided callData
     *      3. Call the callback function with response and UNMODIFIED extraData
     *      4. Display compliance status to user based on callback result
     *      5. Allow/prevent transfer request submission accordingly
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;preCheckCompliance&lt;/span&gt;&lt;span class=&quot;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;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;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 Callback for processing off-chain compliance response (OPTIONAL)
     * @param response Encoded response from off-chain compliance service
     * @param extraData Additional data from original request (passed through unmodified)
     * @return bool Compliance check result
     * @dev Only called by wallets supporting EIP-3668
     *      Validates and interprets off-chain compliance service response
     *
     *      Per [EIP-3668](/EIPS/eip-3668) specification:
     *      - Clients MUST pass extraData unmodified from the OffchainLookup error
     *      - The callback signature MUST match EIP-3668&apos;s standard format
     *      - This enables stateless operation and future extensibility
     *
     *      Example client implementation:
     *      1. Catch OffchainLookup(sender, urls, callData, callbackFunction, extraData)
     *      2. Query off-chain service with callData
     *      3. Call callbackFunction(response, extraData) with UNMODIFIED extraData
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;preCheckComplianceCallback&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;response&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;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;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ============ ERC-1643 Document Management Interface (OPTIONAL) ============
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Implementations MAY support on-chain anchoring of document references.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// RTAs already maintain authoritative books and records off-chain per their
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// regulatory obligations; on-chain anchoring is an optional transparency
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// enhancement, not a compliance requirement.
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Set a document for the token (RTA only) (OPTIONAL)
     * @param _name Document name (unique identifier)
     * @param _uri Document location (IPFS hash or HTTPS URL)
     * @param _documentHash Hash of the document for verification
     * @dev Part of ERC-1643 standard. Only callable by RTA.
     *      Used for storing references to legal documents, compliance certificates,
     *      court orders, recovery evidence, physical addresses, etc.
     *      Never store PII directly on-chain - use document URIs and hashes only.
     *
     *      Common document names:
     *      - &quot;PHYSICAL_ADDRESS&quot;: Issuer&apos;s registered address
     *      - &quot;PROSPECTUS&quot;: Offering documents
     *      - &quot;COURT_ORDER&quot;: Legal judgments
     *      - &quot;RECOVERY_EVIDENCE&quot;: Lost wallet documentation
     *
     *      Implementations providing this function MUST emit DocumentUpdated.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&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;calldata&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;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_documentHash&lt;/span&gt;
    &lt;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 Get a specific document&apos;s details (OPTIONAL)
     * @param _name Document name to retrieve
     * @return documentUri Document location
     * @return documentHash Document hash for verification
     * @return timestamp When document was last updated
     * @dev Part of ERC-1643 standard. Publicly accessible.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&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;n&quot;&gt;documentUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;uint256&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;cm&quot;&gt;/**
     * @notice Remove a document (RTA only) (OPTIONAL)
     * @param _name Document name to remove
     * @dev Part of ERC-1643 standard. Only callable by RTA.
     *      Implementations providing this function MUST emit DocumentRemoved.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes32&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 Get all document names (OPTIONAL)
     * @return Array of all document names that have been set
     * @dev Part of ERC-1643 standard. Publicly accessible.
     *      Allows discovery of all documents associated with the token.
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAllDocuments&lt;/span&gt;&lt;span class=&quot;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;memory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ============ Recovery Workflow for Lost/Compromised Wallets (OPTIONAL) ============
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Uses ERC-1643 for document management and aligns with ERC-1644 for controller operations.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// OPTIONAL: This structured, time-locked workflow is an extension. The REQUIRED
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// baseline for recovery is controllerTransfer — the RTA verifies the investor&apos;s
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// identity through its existing off-chain KYC records and executes the transfer.
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// The structured workflow adds public evidence anchoring and a dispute window
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// for deployments that want on-chain transparency of recovery operations.
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Initiate recovery process for lost wallet (RTA only) (OPTIONAL)
     * @param lostWallet Address that has lost access
     * @param newWallet Proposed replacement address
     * @param documentName Name/type of the supporting document (ERC-1643 compatible)
     * @param uri URI pointing to the evidence document (IPFS/HTTPS)
     * @param documentHash Hash of the document for integrity verification
     * @return recoveryId Unique identifier for the recovery request
     * @dev Creates a time-locked recovery request requiring multi-step verification:
     *      1. Identity verification of the claiming party
     *      2. Proof of ownership (off-chain documentation)
     *      3. Time delay for potential disputes (e.g., 30 days)
     *      4. Final execution after time lock expires
     *
     *      Following ERC-1643 document management standards:
     *      - documentName: Type of evidence (e.g., &quot;RECOVERY_AFFIDAVIT&quot;, &quot;DEATH_CERTIFICATE&quot;)
     *      - uri: Link to encrypted document storage (never store PII on-chain)
     *      - documentHash: Cryptographic hash for document integrity
     *
     *      Implementations providing this function MUST emit DocumentUpdated
     *      per ERC-1643 when evidence is submitted
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiateRecovery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lostWallet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newWallet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentName&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;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentHash&lt;/span&gt;
    &lt;span class=&quot;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;recoveryId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Cancel a pending recovery request (RTA only) (OPTIONAL)
     * @param recoveryId The recovery request to cancel
     * @dev Can be called if:
     *      - Original wallet owner proves they still have access
     *      - Evidence is found to be fraudulent
     *      - Court order requires cancellation
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancelRecovery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recoveryId&lt;/span&gt;&lt;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 Execute recovery after time lock expires (RTA only) (OPTIONAL)
     * @param recoveryId The recovery request to execute
     * @dev Transfers all tokens from lost wallet to new wallet
     *      Can only be executed after time lock period (e.g., 30 days)
     *      Implementations providing this function MUST emit ControllerTransfer
     *      per ERC-1644
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executeRecovery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recoveryId&lt;/span&gt;&lt;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 Controller transfer for court orders (RTA only) - ERC-1644 compatible
     * @param from Source address
     * @param to Destination address
     * @param amount Number of tokens
     * @param data Encoded data containing document references
     * @param operatorData Encoded document information per ERC-1643:
     *        - documentName: Type (e.g., &quot;COURT_ORDER&quot;, &quot;REGULATORY_ACTION&quot;)
     *        - uri: Link to encrypted document storage
     *        - documentHash: Cryptographic hash for integrity
     * @dev Immediate transfer without time lock for:
     *      - Court-ordered transfers (divorce, judgments)
     *      - Regulatory enforcement actions
     *      - Estate distributions with proper documentation
     *
     *      Following ERC-1644 controller operation standards:
     *      - MUST emit ControllerTransfer event
     *      - Uses standard function name for tooling compatibility
     *
     *      Following ERC-1643 document management:
     *      - MUST emit DocumentUpdated event when court order is attached
     *      - Never store PII on-chain, only document URIs and hashes
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controllerTransfer&lt;/span&gt;&lt;span class=&quot;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;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;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;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;operatorData&lt;/span&gt;
    &lt;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;// ============ Account Freezing ============
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Freeze or unfreeze an account (RTA only)
     * @param account Address to freeze/unfreeze
     * @param frozen True to freeze, false to unfreeze
     * @dev Frozen accounts cannot send or receive tokens
     *      Used for compliance holds, regulatory actions, or suspicious activity
     *      Only RTA can freeze/unfreeze accounts
     *      MUST emit AccountFrozen event
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;setAccountFrozen&lt;/span&gt;&lt;span class=&quot;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;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;frozen&lt;/span&gt;&lt;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 Check if an account is frozen
     * @param account Address to check
     * @return bool True if the account is frozen
     * @dev Publicly accessible for transparency
     *      Wallets and exchanges can check before attempting transfers
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isAccountFrozen&lt;/span&gt;&lt;span class=&quot;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;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;c1&quot;&gt;// ============ Recovery System (OPTIONAL) ============
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get recovery request details (OPTIONAL)
     * @param recoveryId The recovery request ID
     * @return lostWallet The wallet being recovered
     * @return newWallet The replacement wallet
     * @return documentName The type of evidence document (ERC-1643)
     * @return documentUri The URI of the evidence document
     * @return documentHash The hash of the evidence document
     * @return initiatedAt Timestamp when recovery was initiated
     * @return status Current status (pending/executed/cancelled)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRecoveryDetails&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recoveryId&lt;/span&gt;&lt;span class=&quot;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;lostWallet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newWallet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentName&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;documentUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;documentHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;uint256&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;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Check if a wallet has a pending recovery
     * @param wallet Address to check
     * @return bool True if wallet has pending recovery
     * @return uint256 Recovery ID if exists, 0 otherwise
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasPendingRecovery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wallet&lt;/span&gt;&lt;span class=&quot;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;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Standard Events from ERC-1644 (Controller Operations)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ControllerTransfer&lt;/span&gt;&lt;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;controller&lt;/span&gt;&lt;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;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;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;n&quot;&gt;operatorData&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;ControllerRedemption&lt;/span&gt;&lt;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;controller&lt;/span&gt;&lt;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;tokenHolder&lt;/span&gt;&lt;span class=&quot;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;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;n&quot;&gt;operatorData&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ERC-1643 Standard Events (Document Management — OPTIONAL, required if
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// the document management extension is implemented)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DocumentUpdated&lt;/span&gt;&lt;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;_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;n&quot;&gt;_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_documentHash&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;DocumentRemoved&lt;/span&gt;&lt;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;_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;n&quot;&gt;_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_documentHash&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Recovery-specific Events (OPTIONAL, required if the recovery workflow
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// extension is implemented)
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RecoveryInitiated&lt;/span&gt;&lt;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;recoveryId&lt;/span&gt;&lt;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;lostWallet&lt;/span&gt;&lt;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;newWallet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timelock&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;RecoveryCancelled&lt;/span&gt;&lt;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;recoveryId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancelledBy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// RecoveryExecuted is replaced by ControllerTransfer event per ERC-1644
&lt;/span&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;interface-detection&quot;&gt;Interface Detection&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1450&lt;/code&gt; interface ID is calculated by XOR’ing the function selectors of all functions unique to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1450&lt;/code&gt; interface (excluding inherited ERC-20 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;// IERC1450 unique functions (not in ERC-20):
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHANGEISSUER&lt;/span&gt; &lt;span class=&quot;o&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;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;changeIssuer(address)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SETTRANSFERAGENT&lt;/span&gt; &lt;span class=&quot;o&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;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;setTransferAgent(address)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ISTRANSFERAGENT&lt;/span&gt; &lt;span class=&quot;o&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;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;isTransferAgent(address)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ISSECURITYTOKEN&lt;/span&gt; &lt;span class=&quot;o&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;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;isSecurityToken()&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINT&lt;/span&gt; &lt;span class=&quot;o&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;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;mint(address,uint256,uint16,uint256)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BURNFROM&lt;/span&gt; &lt;span class=&quot;o&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;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;burnFrom(address,uint256)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BURNFROMREGULATION&lt;/span&gt; &lt;span class=&quot;o&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;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;burnFromRegulation(address,uint256,uint16)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GETHOLDERREGULATIONS&lt;/span&gt; &lt;span class=&quot;o&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;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;getHolderRegulations(address)&quot;&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;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GETREGULATIONSUPPLY&lt;/span&gt; &lt;span class=&quot;o&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;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;getRegulationSupply(uint16)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ... additional IERC1450-specific functions
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// The computed interface ID:
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1450_INTERFACE_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CHANGEISSUER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SETTRANSFERAGENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ISTRANSFERAGENT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ISSECURITYTOKEN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MINT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BURNFROM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BURNFROMREGULATION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GETHOLDERREGULATIONS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GETREGULATIONSUPPLY&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* ^ ... */&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Actual value from reference implementation:
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1450_INTERFACE_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xaf175dee&lt;/span&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;Important Notes on Interface Detection&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Implementations MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface(0x01ffc9a7)&lt;/code&gt; for &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; itself&lt;/li&gt;
  &lt;li&gt;Implementations MUST return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface(0xaf175dee)&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1450&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Implementations SHOULD return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface(type(IERC20Metadata).interfaceId)&lt;/code&gt; for token metadata (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals()&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Implementations MUST NOT return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface(0x36372b07)&lt;/code&gt; for &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why NOT Support ERC-20 Interface ID&lt;/strong&gt;:
While ERC-1450 is ABI-compatible with ERC-20 (same function signatures for view functions), returning &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; for the ERC-20 interface ID (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x36372b07&lt;/code&gt;) would be misleading:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wallets would assume they can call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve()&lt;/code&gt; normally&lt;/li&gt;
  &lt;li&gt;These functions always revert in ERC-1450, breaking user expectations&lt;/li&gt;
  &lt;li&gt;Better to force explicit detection of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1450&lt;/code&gt; to ensure proper UI/UX&lt;/li&gt;
  &lt;li&gt;Returning &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;IERC20Metadata&lt;/code&gt; is acceptable since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol()&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals()&lt;/code&gt; work normally&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;rta-proxy-pattern-required-security-enhancement&quot;&gt;RTA Proxy Pattern (REQUIRED Security Enhancement)&lt;/h3&gt;

&lt;p&gt;To prevent security vulnerabilities where a compromised issuer could change the RTA and steal tokens, ERC-1450 implementations MUST use an RTA Proxy pattern. The reference implementation uses a &lt;strong&gt;generic multi-signature wallet&lt;/strong&gt; that provides maximum flexibility while maintaining security:&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;/**
 * @title RTAProxy
 * @notice Multi-signature proxy contract for RTA operations
 * @dev Deployed once and set as the permanent transferAgent in ERC-1450 tokens
 *
 * The RTAProxy pattern provides:
 * - Protection against single key compromise via M-of-N multi-signature
 * - Generic operation execution (can call any function on any target)
 * - Signer management through multi-sig consensus
 * - Complete audit trail of all RTA actions
 *
 * SECURITY REQUIREMENTS:
 * - MUST use multiple signers (recommended: 2-of-3 or 3-of-5)
 * - Signers SHOULD use hardware wallets or institutional custody
 * - All operations MUST emit events for audit trail
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IRTAProxy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ============ Events ============
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SignerAdded&lt;/span&gt;&lt;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;signer&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;SignerRemoved&lt;/span&gt;&lt;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;signer&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;RequiredSignaturesUpdated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldRequired&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newRequired&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;OperationSubmitted&lt;/span&gt;&lt;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;operationId&lt;/span&gt;&lt;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;submitter&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;OperationConfirmed&lt;/span&gt;&lt;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;operationId&lt;/span&gt;&lt;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;signer&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;OperationExecuted&lt;/span&gt;&lt;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;operationId&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;OperationRevoked&lt;/span&gt;&lt;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;operationId&lt;/span&gt;&lt;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;signer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ============ Errors ============
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NotASigner&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;AlreadyASigner&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;AlreadyConfirmed&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;NotConfirmed&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;InsufficientConfirmations&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;OperationAlreadyExecuted&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;InvalidSignerCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ============ Multi-Sig Operations ============
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Submit a new operation for multi-sig approval
     * @param target The contract to call (e.g., ERC-1450 token address)
     * @param data The encoded function call (e.g., abi.encodeWithSignature(&quot;mint(...)&quot;))
     * @param value ETH value to send (usually 0)
     * @return operationId The ID of the submitted operation
     * @dev Submitter automatically confirms the operation
     *      Operation auto-executes if submitter&apos;s confirmation meets threshold
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;submitOperation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&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;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;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;operationId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Confirm a pending operation
     * @param operationId The operation to confirm
     * @dev Auto-executes when confirmation threshold is met
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confirmOperation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationId&lt;/span&gt;&lt;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 Revoke a previously given confirmation
     * @param operationId The operation to revoke confirmation from
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;revokeConfirmation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationId&lt;/span&gt;&lt;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 Manually execute an operation that has enough confirmations
     * @param operationId The operation to execute
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executeOperation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationId&lt;/span&gt;&lt;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;// ============ Signer Management (via multi-sig) ============
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Add a new signer (requires multi-sig approval)
     * @param signer Address of the new signer
     * @dev MUST be called through submitOperation (msg.sender == address(this))
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addSigner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signer&lt;/span&gt;&lt;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 Remove a signer (requires multi-sig approval)
     * @param signer Address of the signer to remove
     * @dev MUST be called through submitOperation
     *      MUST NOT reduce signers below requiredSignatures
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removeSigner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signer&lt;/span&gt;&lt;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 Update required signature threshold (requires multi-sig approval)
     * @param newRequiredSignatures New threshold
     * @dev MUST be called through submitOperation
     *      MUST be &amp;gt; 0 and &amp;lt;= signers.length
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateRequiredSignatures&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newRequiredSignatures&lt;/span&gt;&lt;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;// ============ View Functions ============
&lt;/span&gt;
    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Get the list of current signers
     * @return Array of signer addresses
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSigners&lt;/span&gt;&lt;span class=&quot;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;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Check if an address has confirmed an operation
     * @param operationId The operation ID
     * @param signer The signer address
     * @return bool True if the signer has confirmed
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasConfirmed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signer&lt;/span&gt;&lt;span class=&quot;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 Get operation details
     * @param operationId The operation ID
     * @return target The target contract
     * @return data The encoded function call
     * @return value The ETH value
     * @return confirmations Number of confirmations
     * @return executed Whether the operation has been executed
     * @return timestamp When the operation was submitted
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getOperation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operationId&lt;/span&gt;&lt;span class=&quot;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;target&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;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;confirmations&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;executed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&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;cm&quot;&gt;/**
     * @notice Returns the contract implementation version
     * @return string Semantic version string (e.g., &quot;1.13.0&quot;)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;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;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;h4 id=&quot;security-benefits&quot;&gt;Security Benefits:&lt;/h4&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Single Key Protection&lt;/strong&gt;: M-of-N multi-sig prevents any single compromised key from executing operations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Issuer Protection&lt;/strong&gt;: Once RTAProxy is set as transferAgent, the issuer cannot unilaterally change it&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexible Operations&lt;/strong&gt;: Generic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;submitOperation&lt;/code&gt; can call any function on any target contract&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Signer Management&lt;/strong&gt;: Add/remove signers and adjust thresholds through multi-sig consensus&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;: All operations are logged on-chain via events&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Revocation&lt;/strong&gt;: Signers can revoke confirmations before execution if needed&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;implementation-flow-required&quot;&gt;Implementation Flow (REQUIRED):&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;1. Deploy RTAProxy with initial signers and threshold (e.g., 3 signers, 2-of-3)
2. Deploy ERC-1450 token with transferAgent = RTAProxy address
3. Token&apos;s setTransferAgent is locked after RTAProxy is set
4. RTA operations flow: Signer → submitOperation → confirmOperation → auto-execute
5. Signer changes require multi-sig approval through submitOperation
6. All operations emit events for regulatory audit trail
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;example-minting-tokens-via-multi-sig&quot;&gt;Example: Minting Tokens via Multi-Sig&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;c1&quot;&gt;// Signer 1 submits mint operation
&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;mintData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodeWithSignature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;mint(address,uint256,uint16,uint256)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;mh&quot;&gt;0x0006&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// REG_US_CF
&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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rtaProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;submitOperation&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;n&quot;&gt;mintData&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;// Signer 2 confirms (auto-executes if 2-of-3)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rtaProxy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;confirmOperation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opId&lt;/span&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;rta-provider-change-process&quot;&gt;RTA Provider Change Process:&lt;/h4&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;When an issuer legitimately needs to change RTA providers:
1. Issuer contracts with new RTA provider
2. Current RTA validates the change request (legal docs, verification)
3. Current RTA transfers records to new RTA
4. Current RTA adds new RTA signers via multi-sig: submitOperation(addSigner(newSigner))
5. Current RTA removes old signers via multi-sig: submitOperation(removeSigner(oldSigner))
6. New RTA now controls all token operations
7. Process is logged on-chain for regulatory compliance
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This cooperative process ensures:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;No unauthorized RTA changes (protects against key compromise)&lt;/li&gt;
  &lt;li&gt;Legitimate business changes are possible (with proper verification)&lt;/li&gt;
  &lt;li&gt;Similar to domain registrar transfers - requires current provider cooperation&lt;/li&gt;
  &lt;li&gt;Creates audit trail for regulators&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;broker-registration-pattern-recommended&quot;&gt;Broker Registration Pattern (RECOMMENDED)&lt;/h3&gt;

&lt;p&gt;While the RTAProxy pattern is REQUIRED for RTA security, a similar BrokerProxy pattern is RECOMMENDED but not required for registered brokers. This provides operational security and key management flexibility for professional broker-dealers.&lt;/p&gt;

&lt;h4 id=&quot;benefits-of-brokerproxy&quot;&gt;Benefits of BrokerProxy:&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Secure key rotation&lt;/strong&gt; without re-registration with the RTA&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Multi-signature controls&lt;/strong&gt; for trader operations&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Business continuity&lt;/strong&gt; during personnel changes&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Institutional custody integration&lt;/strong&gt; (Fireblocks, Coinbase Custody, etc.)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Protection against individual key compromise&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;implementation-options&quot;&gt;Implementation Options:&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Direct Registration (Simple)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RTA → registers → Broker EOA/Multisig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Suitable for: Individual brokers, small operations, testing&lt;/li&gt;
  &lt;li&gt;Risk: Key compromise affects all broker operations&lt;/li&gt;
  &lt;li&gt;Simplicity: No additional contract deployment needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Proxy Pattern (Recommended for Production)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;RTA → registers → BrokerProxy → controls → Operator Multisig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;ul&gt;
  &lt;li&gt;Suitable for: Professional broker-dealers, high-volume operations&lt;/li&gt;
  &lt;li&gt;Benefits: Key rotation, multi-trader support, institutional security&lt;/li&gt;
  &lt;li&gt;Complexity: Requires additional proxy contract deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;example-brokerproxy-interface&quot;&gt;Example BrokerProxy Interface:&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;/**
 * @title IBrokerProxy
 * @notice Optional proxy pattern for registered brokers
 * @dev While not required like RTAProxy, this pattern is RECOMMENDED for:
 *      - Professional broker-dealers with multiple traders
 *      - High-volume brokers needing key rotation
 *      - Brokers using institutional custody solutions
 */&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IBrokerProxy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Events
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OperatorRotated&lt;/span&gt;&lt;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;previousOperator&lt;/span&gt;&lt;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;newOperator&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;RequestSubmitted&lt;/span&gt;&lt;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;requestId&lt;/span&gt;&lt;span class=&quot;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;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 Submit transfer request on behalf of client
     * @dev Only callable by authorized operators of this broker
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;submitTransferRequest&lt;/span&gt;&lt;span class=&quot;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;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;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;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeAmount&lt;/span&gt;
    &lt;span class=&quot;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;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requestId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * @notice Rotate broker operator (multi-sig required)
     * @param newOperator New operator address (should be multi-sig)
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rotateOperator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newOperator&lt;/span&gt;&lt;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 Check if address is authorized operator
     */&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isOperator&lt;/span&gt;&lt;span class=&quot;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;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;h4 id=&quot;why-not-require-brokerproxy&quot;&gt;Why Not REQUIRE BrokerProxy?&lt;/h4&gt;

&lt;p&gt;Unlike the RTA which has ultimate control over all tokens, brokers have limited authority:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Lower Risk&lt;/strong&gt;: Brokers can only request transfers, not execute them&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Business Variety&lt;/strong&gt;: Some brokers are individuals, not institutions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Market Flexibility&lt;/strong&gt;: Let brokers choose security appropriate to their needs&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Gradual Adoption&lt;/strong&gt;: Brokers can upgrade to proxy pattern as they grow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The RTA treats both patterns equally - registration is by address whether direct or proxy. The RTA maintains the right to revoke any broker registration at any time, ensuring ultimate control regardless of the broker’s implementation choice.&lt;/p&gt;

&lt;h3 id=&quot;fee-system-implementation&quot;&gt;Fee System Implementation&lt;/h3&gt;

&lt;p&gt;The fee system allows RTAs to charge for transfer processing using a single configured fee token (typically a stablecoin like USDC):&lt;/p&gt;

&lt;h4 id=&quot;querying-the-fee-token-and-amount&quot;&gt;Querying the Fee Token and Amount&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;c1&quot;&gt;// Get the configured fee token
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeToken&lt;/span&gt; &lt;span class=&quot;o&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;getFeeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Returns: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 (USDC on mainnet)
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Get the fee amount for a transfer
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;feeAmount&lt;/span&gt; &lt;span class=&quot;o&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;getTransferFee&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;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;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Returns: 10000000 (10 USDC with 6 decimals) for flat fee
// OR calculated percentage for percentage-based fees
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;frontend-implementation-pattern&quot;&gt;Frontend Implementation Pattern&lt;/h4&gt;

&lt;div class=&quot;language-javascript highlighter-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;// Get the fee token and amount&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;feeToken&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&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;getFeeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;feeAmount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&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;getTransferFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Get token info for display&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tokenInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;getTokenInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;feeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;formattedFee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;formatUnits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;feeAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tokenInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;decimals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Display to user: &quot;Transfer fee: 10.00 USDC&quot;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`Transfer fee: &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;formattedFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tokenInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;symbol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Ensure user has approved fee token spending&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;feeTokenContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;approve&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;nx&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;feeAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Submit transfer request with fee&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;requestId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&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;requestTransferWithFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;feeAmount&lt;/span&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;rta-fee-configuration&quot;&gt;RTA Fee Configuration&lt;/h4&gt;

&lt;p&gt;RTAs configure the fee system through 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;// Set the fee token (typically USDC or another stablecoin)
&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;setFeeToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;USDC_ADDRESS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Set fee parameters
// Type 0: Flat fee (feeValue is the exact amount in fee token units)
&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;setFeeParameters&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;10000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 10 USDC flat fee
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Type 1: Percentage fee (feeValue is basis points, 100 = 1%)
&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;setFeeParameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 0.5% fee
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;implementation-requirements-for-regulated-securities&quot;&gt;Implementation Requirements for Regulated Securities&lt;/h3&gt;
&lt;p&gt;This standard requires implementers to maintain off-chain services and databases that record and track investor information including names, physical addresses, Ethereum addresses, and security ownership amounts. Before associating any Ethereum address with an investor’s identity, implementers MUST verify ownership of that address through cryptographic proof (such as message signing), micro-deposits, or other secure verification methods to prevent fraudulent claims.&lt;/p&gt;

&lt;p&gt;The designated transfer agent must be able to produce current lists of all investors, including their identities and security ownership levels at any given moment. The system must support re-issuance of securities to investors for various operational and regulatory reasons.&lt;/p&gt;

&lt;p&gt;Private investor information must never be publicly exposed on a public blockchain.&lt;/p&gt;

&lt;h3 id=&quot;kycaml-requirements&quot;&gt;KYC/AML Requirements&lt;/h3&gt;

&lt;p&gt;Per SEC regulations and the Bank Secrecy Act, the RTA MUST ensure:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Identity Verification&lt;/strong&gt;: Every address holding tokens MUST be associated with a verified natural or legal person who has passed KYC/AML checks&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Address Ownership Proof&lt;/strong&gt;: Before any transfer, the RTA MUST verify that the recipient address is controlled by a verified person (via signature, micro-deposit, or other secure method)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Ongoing Monitoring&lt;/strong&gt;: The RTA MUST maintain current KYC/AML status and may freeze accounts that fail periodic reviews&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Anonymous Holdings&lt;/strong&gt;: Unlike permissionless tokens, ERC-1450 tokens CANNOT be held by anonymous or unverified addresses&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The RTA enforces these requirements through:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;: RTA only executes after verifying both parties&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestTransferWithFee&lt;/code&gt;: RTA rejects requests to unverified addresses with appropriate reason codes (10-14)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;: RTA only mints to verified addresses&lt;/li&gt;
  &lt;li&gt;Recovery mechanisms: Require identity verification before execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Transfer rejections for KYC/AML failures use specific reason codes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REASON_RECIPIENT_NOT_VERIFIED&lt;/code&gt; (10): Recipient hasn’t completed KYC/AML&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REASON_ADDRESS_NOT_LINKED&lt;/code&gt; (11): Address not linked to verified identity&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REASON_SENDER_VERIFICATION_EXPIRED&lt;/code&gt; (12): Sender’s KYC expired&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REASON_JURISDICTION_BLOCKED&lt;/code&gt; (13): Recipient in restricted jurisdiction&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REASON_ACCREDITATION_REQUIRED&lt;/code&gt; (14): Recipient not accredited (for Reg D offerings)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;managing-investor-information&quot;&gt;Managing Investor Information&lt;/h3&gt;
&lt;p&gt;Special care and attention must be taken to ensure that the personally identifiable information of Investors is never exposed or revealed to the public.&lt;/p&gt;

&lt;h3 id=&quot;issuers-who-lost-access-to-their-address-or-private-keys&quot;&gt;Issuers who lost access to their address or private keys&lt;/h3&gt;
&lt;p&gt;With the RTA Proxy pattern implemented in ERC-1450, the impact of an Issuer losing access to their private key is significantly mitigated. Once the RTA is established (especially via RTAProxy), the RTA maintains exclusive control over critical operations including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeIssuer&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burn&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;. Even if the Issuer loses their private key or becomes compromised, the RTA can:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Continue all token operations without issuer involvement&lt;/li&gt;
  &lt;li&gt;Transfer ownership to a new issuer address through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeIssuer&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Protect token holders from any issuer-side security failures&lt;/li&gt;
  &lt;li&gt;Maintain full regulatory compliance and operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design ensures that securities tokens remain operational and secure regardless of issuer key management issues. The RTA acts as the security backstop, preventing any single point of failure from disrupting the securities’ operations or endangering investor assets.&lt;/p&gt;

&lt;p&gt;If the Issuer loses access, the Issuer’s securities must be rebuilt using off-chain services. The Issuer must create (and secure) a new address. The RTA can read the existing Issuer securities, and the RTA can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt; Investor securities accordingly under a new ERC-1450 smart contract.&lt;/p&gt;

&lt;h3 id=&quot;registered-transfer-agents-who-lost-access-to-their-address-or-private-keys&quot;&gt;Registered Transfer Agents who lost access to their address or private keys&lt;/h3&gt;
&lt;p&gt;Professional RTAs MUST implement enterprise-grade key management solutions to prevent key loss scenarios. This includes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Multi-signature wallets requiring multiple parties to approve transactions&lt;/li&gt;
  &lt;li&gt;Hardware Security Modules (HSMs) for key storage&lt;/li&gt;
  &lt;li&gt;Multi-Party Computation (MPC) solutions like Fireblocks or similar institutional custody&lt;/li&gt;
  &lt;li&gt;Geographically distributed key shards&lt;/li&gt;
  &lt;li&gt;Regular key rotation and backup procedures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With proper security infrastructure, RTA key loss should be virtually impossible. However, if catastrophic failure occurs:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;With RTAProxy pattern: The proxy contract can facilitate controlled RTA rotation with proper authorization&lt;/li&gt;
  &lt;li&gt;Without RTAProxy: The Issuer can execute &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setTransferAgent&lt;/code&gt; to assign a new RTA address (if the issuer still has access)&lt;/li&gt;
  &lt;li&gt;Last resort: Securities must be reissued on a new contract with proper verification of all holdings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The use of professional custody solutions by RTAs is not optional but essential for maintaining the security and reliability required for managing securities.&lt;/p&gt;

&lt;h3 id=&quot;handling-investors-security-owners-who-lost-access-to-their-addresses-or-private-keys&quot;&gt;Handling Investors (security owners) who lost access to their addresses or private keys&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Common Business Model - RTA Omnibus Custody:&lt;/strong&gt;
Many RTAs maintain securities in omnibus accounts with off-chain record keeping of individual investor holdings. This business model (not a protocol requirement) offers several advantages:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Most investors never need to manage private keys&lt;/li&gt;
  &lt;li&gt;Internal transfers occur off-chain in databases&lt;/li&gt;
  &lt;li&gt;Securities only transfer to investor wallets upon explicit, verified request&lt;/li&gt;
  &lt;li&gt;Investor key loss doesn’t affect their holdings in the omnibus account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: This is a business implementation choice, not enforced by the protocol itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-Custody Scenario:&lt;/strong&gt;
For investors who choose to hold securities in their own wallets, loss of credentials may occur due to: lost private keys, hacking, fraud, or life events (death, incapacitation). In these cases:&lt;/p&gt;

&lt;p&gt;If an Investor (or their legal representative) loses wallet access, they must go through a verified process with the RTA including:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Identity verification matching original KYC records&lt;/li&gt;
  &lt;li&gt;Notarized affidavit of lost access&lt;/li&gt;
  &lt;li&gt;Waiting period for potential disputes (as specified in recovery mechanism)&lt;/li&gt;
  &lt;li&gt;Supply and verify ownership of new wallet address&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Upon successful verification, the RTA can use the recovery mechanism to transfer securities from the lost wallet to the new verified wallet, maintaining full audit trail for regulatory compliance.&lt;/p&gt;

&lt;p&gt;Note: The omnibus custody model described above is a common business practice that provides professional security while maintaining investor flexibility to withdraw to self-custody when desired. This is an implementation choice, not a protocol requirement.&lt;/p&gt;

&lt;h3 id=&quot;regulation-tracking-implementation-non-normative&quot;&gt;Regulation Tracking Implementation (Non-Normative)&lt;/h3&gt;

&lt;p&gt;This section provides guidance for implementing regulation tracking in ERC-1450 tokens. Since securities must be issued under specific regulatory frameworks, implementations need to track which regulation applies to each token holder’s shares for proper compliance enforcement.&lt;/p&gt;

&lt;h4 id=&quot;regulation-type-encoding&quot;&gt;Regulation Type Encoding&lt;/h4&gt;

&lt;p&gt;Implementations SHOULD use a uint16 value to encode regulation types, allowing for global regulatory frameworks. A suggested encoding pattern uses the high byte for country/region and the low byte for specific regulations:&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;// Example encoding (not part of the standard, implementations may vary):
// Format: 0xCCRR where CC = country code, RR = regulation code
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// US Regulations (0x00XX)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_S1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0001&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// S-1 Registration (IPO)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_D_504&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0002&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Regulation D Rule 504 ($10M)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_A_TIER_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0004&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// Regulation A Tier I ($20M)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_A_TIER_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0005&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;// Regulation A Tier II ($75M)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_CF&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0006&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Regulation Crowdfunding ($5M)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_D_506B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0007&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// Regulation D 506(b) (no general solicitation)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_D_506C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0008&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// Regulation D 506(c) (accredited only)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_US_S&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0009&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Regulation S (offshore offerings)
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// EU Regulations (0x01XX)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_EU_PROSPECTUS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0101&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// EU Prospectus Regulation
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Canadian Regulations (0x02XX)
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;constant&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REG_CA_OM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0201&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;// Offering Memorandum
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;storage-pattern&quot;&gt;Storage Pattern&lt;/h4&gt;

&lt;p&gt;Implementations MUST store regulation data on-chain to enable the RTA to enforce compliance. A recommended storage pattern:&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;TokenBatch&lt;/span&gt; &lt;span class=&quot;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;kt&quot;&gt;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;regulationType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;issuanceDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Original share issuance, not tokenization
&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;n&quot;&gt;TokenBatch&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;holderBatches&lt;/span&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;compliance-checking&quot;&gt;Compliance Checking&lt;/h4&gt;

&lt;p&gt;When processing transfer requests, the RTA queries the regulation data to apply appropriate restrictions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Time-based restrictions&lt;/strong&gt;: Calculate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;currentTime - issuanceDate&lt;/code&gt; to determine if holding periods have expired&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Investor restrictions&lt;/strong&gt;: Check if recipient meets requirements (e.g., accreditation for Reg D)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Geographic restrictions&lt;/strong&gt;: Verify jurisdiction compliance for regulations like Reg S&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;example-reg-cf-maturation&quot;&gt;Example: Reg CF Maturation&lt;/h4&gt;

&lt;p&gt;Regulation Crowdfunding shares have a 12-month resale restriction that expires over time:&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;// At mint time (tokenizing shares from March 2023 offering)
&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;investor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0006&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1677628800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// REG_US_CF, March 1, 2023
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Transfer request in November 2024
// RTA calculates: Nov 2024 - March 2023 = 20 months (&amp;gt; 12 months)
// Result: Shares have matured, transfer allowed to any eligible investor
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Transfer request if it had been May 2023
// RTA calculates: May 2023 - March 2023 = 2 months (&amp;lt; 12 months)
// Result: Transfer blocked with REASON_LOCK_PERIOD
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;rta-transfer-strategy-flexibility&quot;&gt;RTA Transfer Strategy Flexibility&lt;/h4&gt;

&lt;p&gt;The RTA has complete control over which token batches to transfer or burn. The blockchain stores raw batch data, while the RTA implements the optimal strategy for each situation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transfer Strategy Options:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Holder has:
// - 100 tokens: Reg CF, issued March 2023
// - 200 tokens: Reg D, issued June 2023
// - 50 tokens: Reg A, issued September 2023
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Transfer request for 150 tokens - RTA chooses strategy:
// Option A (FIFO): transferFromRegulated(..., 100, REG_CF, March2023)
//                  transferFromRegulated(..., 50, REG_D, June2023)
// Option B (LIFO): transferFromRegulated(..., 50, REG_A, Sept2023)
//                  transferFromRegulated(..., 100, REG_D, June2023)
// Option C (Tax Optimized): Transfer specific lots for best tax outcome
// Option D (Regulatory): Transfer only matured/unrestricted batches
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Burn Strategy Options:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Using burnFrom(address, amount) - RTA determines strategy
// Using burnFromRegulated(address, amount, regulation, date) - Precise control
// Using burnFromRegulation(address, amount, regulation) - Regulation-specific
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// RTA can optimize based on:
// - Tax implications (short vs long-term gains)
// - Regulatory maturity (expired lockups first)
// - Holder preferences (specific lot selection)
// - Corporate actions (specific share class redemption)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This flexibility ensures:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Tax optimization for holders&lt;/li&gt;
  &lt;li&gt;Regulatory compliance per jurisdiction&lt;/li&gt;
  &lt;li&gt;Support for various accounting methods&lt;/li&gt;
  &lt;li&gt;Adaptability to changing requirements&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;corporate-actions-non-normative&quot;&gt;Corporate Actions (Non-Normative)&lt;/h3&gt;

&lt;p&gt;This section describes recommended patterns for implementing common corporate actions in ERC-1450 tokens. These patterns demonstrate operational completeness while maintaining the core security and compliance model.&lt;/p&gt;

&lt;h4 id=&quot;stock-splits-and-reverse-splits&quot;&gt;Stock Splits and Reverse Splits&lt;/h4&gt;

&lt;p&gt;For stock splits (e.g., 2-for-1) or reverse splits (e.g., 1-for-10), the RTA executes proportional adjustments:&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;// 2-for-1 split implementation pattern
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executeSplit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;splitRatio&lt;/span&gt;&lt;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;onlyRTA&lt;/span&gt; &lt;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;holders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getAllHolders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Off-chain tracked
&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;uint&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;holders&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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentBalance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;balanceOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;holders&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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;additionalShares&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;currentBalance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;splitRatio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Mint additional shares
&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;holders&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;additionalShares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Emit canonical events for indexers
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Transfer&lt;/span&gt;&lt;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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;holders&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;additionalShares&lt;/span&gt;&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;&lt;strong&gt;Key Implementation Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;RTA executes atomically across all holders&lt;/li&gt;
  &lt;li&gt;Uses canonical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer(0x0, holder, amount)&lt;/code&gt; events for mints&lt;/li&gt;
  &lt;li&gt;For reverse splits, use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_burn&lt;/code&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Transfer(holder, 0x0, amount)&lt;/code&gt; events&lt;/li&gt;
  &lt;li&gt;Maintain audit trail with split ratio and execution timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;dividends-and-distributions&quot;&gt;Dividends and Distributions&lt;/h4&gt;

&lt;p&gt;Dividend payments typically use stablecoin distributions based on a record date snapshot:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Off-Chain Distribution List&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// RTA takes snapshot at record date
&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;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDateBalances&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Off-chain: Calculate pro-rata distributions
// Execute stablecoin transfers via separate contract or traditional rails
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Option 2: On-Chain Claim Contract&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DividendClaim&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC20&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;paymentToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// e.g., USDC
&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;uint256&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;claimableAmounts&lt;/span&gt;&lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claim&lt;/span&gt;&lt;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;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isKYCVerified&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;s&quot;&gt;&quot;KYC required&quot;&lt;/span&gt;&lt;span class=&quot;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;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;claimableAmounts&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;claimableAmounts&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;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;paymentToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;transfer&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;amount&lt;/span&gt;&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;&lt;strong&gt;Implementation Notes:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Record date snapshot determines eligible holders&lt;/li&gt;
  &lt;li&gt;Payment in stablecoins (USDC, USDT) or native tokens (ETH, MATIC)&lt;/li&gt;
  &lt;li&gt;Tax withholding handled off-chain per jurisdiction&lt;/li&gt;
  &lt;li&gt;RTA maintains distribution records for tax reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;mandatory-redemptions-and-calls&quot;&gt;Mandatory Redemptions and Calls&lt;/h4&gt;

&lt;p&gt;For mandatory redemptions (e.g., bond calls, forced buybacks), use Controller Token Operation Standard (1644) semantics:&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;executeMandatoryRedemption&lt;/span&gt;&lt;span class=&quot;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;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pricePerShare&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;n&quot;&gt;onlyRTA&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Force transfer to redemption pool
&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;n&quot;&gt;holder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;redemptionPool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Record redemption terms
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Redemption&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;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pricePerShare&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&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;c1&quot;&gt;// Payment handled via separate mechanism
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// (stablecoin transfer, wire, check)
&lt;/span&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;Compliance Requirements:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Follow Document Management Standard (1643) for notices and terms&lt;/li&gt;
  &lt;li&gt;Provide advance notice per security agreements (typically 30-60 days)&lt;/li&gt;
  &lt;li&gt;Maintain redemption price and payment terms on-chain or via Document Management Standard&lt;/li&gt;
  &lt;li&gt;Support partial redemptions for pro-rata calls&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;tender-offers&quot;&gt;Tender Offers&lt;/h4&gt;

&lt;p&gt;Voluntary tender offers allow investors to optionally sell shares:&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;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TenderOffer&lt;/span&gt; &lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offerPrice&lt;/span&gt;&lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offerExpiry&lt;/span&gt;&lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offeror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;acceptOffer&lt;/span&gt;&lt;span class=&quot;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;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offerExpiry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Offer 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;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isKYCVerified&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;s&quot;&gt;&quot;KYC required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Transfer shares to offeror
&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;requestTransferWithFee&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;offeror&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Payment handled separately
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OfferAccepted&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;amount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offerPrice&lt;/span&gt;&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;mergers-and-acquisitions&quot;&gt;Mergers and Acquisitions&lt;/h4&gt;

&lt;p&gt;For mergers requiring token swaps:&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;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MergerExchange&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC1450&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;oldToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC1450&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newToken&lt;/span&gt;&lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exchangeRatio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// e.g., 100 = 1:1, 150 = 1.5:1
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exchangeTokens&lt;/span&gt;&lt;span class=&quot;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;nb&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isKYCVerified&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;s&quot;&gt;&quot;KYC required&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Burn old tokens
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;oldToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requestTransferWithFee&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;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;n&quot;&gt;amount&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;// Mint new tokens at exchange ratio
&lt;/span&gt;        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newAmount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;amount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exchangeRatio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;newToken&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;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;newAmount&lt;/span&gt;&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;implementation-considerations&quot;&gt;Implementation Considerations&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Event Standardization&lt;/strong&gt;: Use canonical Transfer events for all balance changes to ensure indexer compatibility&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Record Dates&lt;/strong&gt;: Snapshot mechanisms must account for pending transfers and corporate action timelines&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Payment Rails&lt;/strong&gt;: Dividend and redemption payments typically use stablecoins or traditional banking&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Notices&lt;/strong&gt;: Use Document Management Standard (1643) for required disclosures&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tax Compliance&lt;/strong&gt;: Off-chain systems handle withholding and reporting requirements&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;: All corporate actions must maintain complete records for regulatory review&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These patterns demonstrate that ERC-1450 can handle the complete lifecycle of security token operations while maintaining regulatory compliance and investor protections. The RTA’s exclusive control ensures all corporate actions are executed properly with appropriate verification and documentation.&lt;/p&gt;

&lt;h3 id=&quot;record-dates-and-voting-mechanics-non-normative&quot;&gt;Record Dates and Voting Mechanics (Non-Normative)&lt;/h3&gt;

&lt;p&gt;Securities require record dates for corporate actions, proxy voting, and shareholder meetings. This section provides guidance on implementing these features without complicating the core token standard.&lt;/p&gt;

&lt;h4 id=&quot;record-date-snapshots&quot;&gt;Record Date Snapshots&lt;/h4&gt;

&lt;p&gt;Record dates determine which shareholders are eligible for dividends, voting, or other corporate actions. Rather than building snapshots into the token itself, we recommend:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Off-Chain Snapshots (Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// RTA maintains historical balances in database
// Query: SELECT balance FROM holdings WHERE address = ? AND timestamp &amp;lt;= ?
// This provides complete flexibility without on-chain gas costs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Option 2: External Snapshot Contract&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Use existing snapshot solutions like OpenZeppelin&apos;s ERC20Snapshot
// or deploy a separate SnapshotManager contract
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ISnapshotManager&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;takeSnapshot&lt;/span&gt;&lt;span class=&quot;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;snapshotId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;balanceOfAt&lt;/span&gt;&lt;span class=&quot;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;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotId&lt;/span&gt;&lt;span class=&quot;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;&lt;strong&gt;Option 3: Simple Block-Based Recording&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// For simple needs, just record block numbers
&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;uint256&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDates&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// actionId =&amp;gt; blockNumber
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Off-chain services can reconstruct balances at any block
// using historical blockchain data
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;voting-and-proxy-management&quot;&gt;Voting and Proxy Management&lt;/h4&gt;

&lt;p&gt;Shareholder voting for corporate governance (board elections, mergers, etc.) is typically handled off-chain with on-chain attestation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proxy Rules Documentation&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Store proxy voting rules via ERC-1643 document management
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;PROXY_RULES_2024&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;ipfs://QmProxyVotingRulesHash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&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;Voting Process Pattern&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VotingRegistry&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;ProxyVote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;votingDeadline&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;proposalUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// IPFS link to proposal details
&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;n&quot;&gt;hasVoted&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;uint256&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;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;votes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// optionId =&amp;gt; voteCount
&lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// RTA records votes submitted through traditional proxy channels
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordVote&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shareholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optionId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;
    &lt;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;onlyRTA&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;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;balanceOfAt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shareholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDate&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;shares&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;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasVoted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shareholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Already voted&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;votes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optionId&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;shares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;hasVoted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shareholder&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;VoteRecorded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shareholder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;optionId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;&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;quorum-and-meeting-mechanics&quot;&gt;Quorum and Meeting Mechanics&lt;/h4&gt;

&lt;p&gt;For shareholder meetings requiring quorum:&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;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MeetingQuorum&lt;/span&gt; &lt;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;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorumPercentage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 50% in basis points
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculateQuorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recordDate&lt;/span&gt;&lt;span class=&quot;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;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;totalSupply&lt;/span&gt; &lt;span class=&quot;o&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;totalSupply&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;totalSupply&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quorumPercentage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&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;isQuorumMet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;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;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;totalVoted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getTotalVotes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calculateQuorum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;votes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recordDate&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;totalVoted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;required&lt;/span&gt;&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;implementation-recommendations&quot;&gt;Implementation Recommendations&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Keep the Token Simple&lt;/strong&gt;: Don’t add snapshot logic to the core ERC-1450 token. Use external contracts or off-chain systems.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Document Everything&lt;/strong&gt;: Use Document Management Standard (1643) to store:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PROXY_RULES&lt;/code&gt; - Voting procedures and requirements&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MEETING_NOTICE&lt;/code&gt; - Shareholder meeting announcements&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RECORD_DATE&lt;/code&gt; - Official record date declarations&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VOTING_RESULTS&lt;/code&gt; - Final vote tallies and outcomes&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Hybrid Approach&lt;/strong&gt;: Most voting happens off-chain through traditional proxy systems, with results attested on-chain by the RTA.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Compliance&lt;/strong&gt;: Follow SEC rules for proxy solicitation, including:
    &lt;ul&gt;
      &lt;li&gt;Proper notice periods (typically 10-60 days)&lt;/li&gt;
      &lt;li&gt;Required disclosures in proxy statements&lt;/li&gt;
      &lt;li&gt;Vote tabulation by independent inspectors of election&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;: Maintain complete records of:
    &lt;ul&gt;
      &lt;li&gt;Record date declarations&lt;/li&gt;
      &lt;li&gt;Shareholder eligibility&lt;/li&gt;
      &lt;li&gt;Votes submitted&lt;/li&gt;
      &lt;li&gt;Final results and actions taken&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;example-integration&quot;&gt;Example Integration&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;c1&quot;&gt;// Complete voting lifecycle example
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ShareholderGovernance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC1450&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&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;ISnapshotManager&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;initiateVote&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;proposalUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;votingPeriodDays&lt;/span&gt;
    &lt;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;onlyRTA&lt;/span&gt; &lt;span class=&quot;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;voteId&lt;/span&gt;&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;// 1. Take snapshot for record date
&lt;/span&gt;        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;takeSnapshot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// 2. Store proposal details via ERC-1643
&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;setDocument&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;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;PROPOSAL_&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;proposalUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// 3. Set voting deadline
&lt;/span&gt;        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deadline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;votingPeriodDays&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;kc&quot;&gt;days&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// 4. Emit event for indexers and shareholders
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;VoteInitiated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voteId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;snapshotId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deadline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;proposalUri&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;voteId&lt;/span&gt;&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;This approach answers the “how do I do meetings?” question while keeping the core ERC-1450 token simple and focused on transfer control. RTAs can implement voting and governance in whatever way best suits their jurisdiction and security type, using the token as the source of truth for ownership while handling the mechanics externally.&lt;/p&gt;

&lt;h3 id=&quot;tax-and-withholding-obligations-non-normative&quot;&gt;Tax and Withholding Obligations (Non-Normative)&lt;/h3&gt;

&lt;p&gt;Tax compliance for security tokens is handled entirely off-chain by the RTA. This section documents common patterns for managing tax obligations without adding on-chain complexity.&lt;/p&gt;

&lt;h4 id=&quot;tax-documentation-collection&quot;&gt;Tax Documentation Collection&lt;/h4&gt;

&lt;p&gt;RTAs must collect appropriate tax documentation before enabling trading:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;U.S. Persons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;W-9 Forms&lt;/strong&gt;: Collected during KYC for U.S. tax residents&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Taxpayer Identification Number (TIN)&lt;/strong&gt;: Stored securely off-chain&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Backup Withholding&lt;/strong&gt;: Applied when W-9 not provided (24% as of 2024)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Non-U.S. Persons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;W-8 Forms&lt;/strong&gt;: Various types (W-8BEN, W-8BEN-E, W-8IMY, etc.)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Foreign TIN&lt;/strong&gt;: When available under tax treaties&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;FATCA/CRS Compliance&lt;/strong&gt;: Automatic exchange of information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation references stored via Document Management Standard (1643):&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;// Store encrypted reference to tax documentation
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;TAX_DOCS_2024&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;ipfs://QmTaxDocumentationHash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Encrypted off-chain storage
&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;withholding-at-source&quot;&gt;Withholding at Source&lt;/h4&gt;

&lt;p&gt;For dividends and distributions, withholding occurs off-chain:&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;// Example: Dividend payment with withholding (off-chain calculation)
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DividendPayment&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recipient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;grossAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;withholdingRate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// e.g., 3000 = 30%
&lt;/span&gt;    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;netAmount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;// grossAmount - withholding
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// RTA calculates withholding based on:
// - Investor tax status (US vs. non-US)
// - Security type (equity vs. debt)
// - Tax treaty benefits
// - Dividend type (ordinary vs. qualified)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;tax-reporting&quot;&gt;Tax Reporting&lt;/h4&gt;

&lt;p&gt;Annual tax reporting handled entirely off-chain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1099 Series (U.S. Recipients):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;1099-DIV&lt;/strong&gt;: Dividend distributions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;1099-B&lt;/strong&gt;: Proceeds from broker transactions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;1099-INT&lt;/strong&gt;: Interest payments&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;1099-MISC&lt;/strong&gt;: Other income&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1042-S (Non-U.S. Recipients):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Foreign person’s U.S. source income&lt;/li&gt;
  &lt;li&gt;Withholding tax applied&lt;/li&gt;
  &lt;li&gt;Treaty benefits claimed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reporting references maintained via document management:&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;// Annual tax reporting references
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;1099_FORMS_2024&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;encrypted://tax-reports/2024/1099&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;rtaContract&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDocument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;1042S_FORMS_2024&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;encrypted://tax-reports/2024/1042s&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&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;implementation-pattern&quot;&gt;Implementation Pattern&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;c1&quot;&gt;// Off-chain tax compliance system interfaces with on-chain token
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ITaxCompliance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// All functions are off-chain, shown here for documentation
&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collectW9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;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;collectW8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;W8Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;formType&lt;/span&gt;&lt;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;calculateWithholding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;span class=&quot;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;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;generate1099&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;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;generate1042S&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;investor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;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;// On-chain reference only
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updateTaxDocumentHash&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;docType&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;uri&lt;/span&gt;&lt;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;h4 id=&quot;key-principles&quot;&gt;Key Principles&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;No On-Chain Tax Logic&lt;/strong&gt;: All tax calculations and withholding happen off-chain&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Document References Only&lt;/strong&gt;: Use Document Management Standard (1643) to store encrypted references to tax documents&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Privacy Protection&lt;/strong&gt;: Never store TINs, SSNs, or tax rates on-chain&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Jurisdictional Flexibility&lt;/strong&gt;: RTAs handle varying tax requirements per jurisdiction&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;: Maintain complete off-chain records for tax authority audits&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;operational-workflow&quot;&gt;Operational Workflow&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Onboarding&lt;/strong&gt;: Collect W-9/W-8 during KYC process&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Distributions&lt;/strong&gt;: Calculate withholding off-chain before payment&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trading&lt;/strong&gt;: Track cost basis off-chain for 1099-B reporting&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Year-End&lt;/strong&gt;: Generate tax forms and provide to investors&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Compliance&lt;/strong&gt;: File with IRS/tax authorities as required&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach ensures full tax compliance while keeping the token standard simple and avoiding the complexity of on-chain tax calculations. Tax obligations remain where they belong - in the operational layer managed by the regulated RTA.&lt;/p&gt;

&lt;h3 id=&quot;ats-adapter-pattern-non-normative&quot;&gt;ATS Adapter Pattern (Non-Normative)&lt;/h3&gt;

&lt;p&gt;While ERC-1450 explicitly excludes DEX trading due to compliance requirements, regulated Alternative Trading Systems (ATSs) and other SEC-registered venues can integrate with ERC-1450 tokens to provide compliant secondary market liquidity.&lt;/p&gt;

&lt;h4 id=&quot;monitoring-transfer-events-for-liquidity-discovery&quot;&gt;Monitoring Transfer Events for Liquidity Discovery&lt;/h4&gt;

&lt;p&gt;Regulated trading venues can monitor existing ERC-1450 events to facilitate compliant trading:&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;// Existing events that ATSs can monitor
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransferRequested&lt;/span&gt;&lt;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;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;fee&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;TransferApproved&lt;/span&gt;&lt;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;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;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TransferRejected&lt;/span&gt;&lt;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;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;uint16&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;ats-integration-patterns&quot;&gt;ATS Integration Patterns&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Pattern 1: Order Book Visibility&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ATS monitors TransferRequested events to understand market interest
// Can display pending transfer requests as &quot;indications of interest&quot;
// Note: Actual execution still requires RTA approval
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Pattern 2: Pre-Matched Trade Submission&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ATS matches buyers and sellers off-chain
// Submits transfer via registered broker
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;submitMatchedTrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buyer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;
&lt;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;registeredBrokers&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;s&quot;&gt;&quot;Must be registered broker&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Route through standard transfer request
&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;requestTransferWithFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buyer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;brokerFee&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;Pattern 3: Failed Transfer Analysis&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// ATS monitors TransferRejected events with reason codes
// Uses this data to:
// - Pre-filter non-compliant trades
// - Understand liquidity constraints
// - Improve matching algorithms
&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;reasonCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_RECIPIENT_NOT_VERIFIED&lt;/span&gt;&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;// Don&apos;t match with this buyer until KYC complete
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reasonCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;REASON_INSUFFICIENT_BALANCE&lt;/span&gt;&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;// Seller doesn&apos;t have shares available
&lt;/span&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;compliant-venue-integration&quot;&gt;Compliant Venue Integration&lt;/h4&gt;

&lt;p&gt;Regulated venues can facilitate liquidity while maintaining full compliance:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Pre-Trade Compliance&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Verify all parties are KYC/AML approved&lt;/li&gt;
      &lt;li&gt;Check transfer restrictions before matching&lt;/li&gt;
      &lt;li&gt;Ensure accreditation requirements are met&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Trade Execution&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Submit transfers through registered broker accounts&lt;/li&gt;
      &lt;li&gt;Include appropriate fees in transfer requests&lt;/li&gt;
      &lt;li&gt;Maintain audit trail for regulatory review&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Post-Trade Settlement&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;Monitor TransferApproved events for confirmation&lt;/li&gt;
      &lt;li&gt;Handle failed transfers based on reason codes&lt;/li&gt;
      &lt;li&gt;Report trades to regulatory systems (CAT, TRACE, etc.)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;example-ats-adapter-implementation&quot;&gt;Example ATS Adapter Implementation&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;k&quot;&gt;contract&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ATSAdapter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;IERC1450&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&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;address&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rtaAddress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Track pending orders
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Order&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trader&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;isBuy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;price&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;isActive&lt;/span&gt;&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;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Order&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;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Submit matched trades to RTA
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;executeTrade&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buyOrderId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sellOrderId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;
    &lt;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;onlyATS&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Order&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buyOrder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buyOrderId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Order&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sellOrder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sellOrderId&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;buyOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isBuy&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;sellOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isBuy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Invalid order types&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;buyOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isActive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sellOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&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;s&quot;&gt;&quot;Orders not active&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Pre-verify compliance
&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isKYCVerified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buyOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Buyer not KYC&apos;d&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isKYCVerified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sellOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Seller not KYC&apos;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// Submit transfer through registered broker
&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;requestTransferWithFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;sellOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buyOrder&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;calculateFee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shares&lt;/span&gt;&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;// Mark orders as pending execution
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buyOrderId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isActive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sellOrderId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isActive&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;false&lt;/span&gt;&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;// Monitor rejection reasons to update order book
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handleRejection&lt;/span&gt;&lt;span class=&quot;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;uint16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reasonCode&lt;/span&gt;
    &lt;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;// Update order book based on rejection reason
&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;reasonCode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// REASON_RECIPIENT_NOT_VERIFIED
&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Remove buy orders from this recipient
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;cancelOrdersForTrader&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;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;benefits-of-ats-integration&quot;&gt;Benefits of ATS Integration&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Compliant Liquidity&lt;/strong&gt;: Provides secondary market without compromising KYC/AML&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Price Discovery&lt;/strong&gt;: Enables transparent pricing through regulated venues&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Reporting&lt;/strong&gt;: Maintains full audit trail for SEC/FINRA requirements&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Investor Protection&lt;/strong&gt;: All trades go through regulated entities with oversight&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Efficiency&lt;/strong&gt;: Reduces settlement risk through pre-verification&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 id=&quot;important-considerations&quot;&gt;Important Considerations&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Not DEX Trading&lt;/strong&gt;: All transfers still require RTA approval and KYC verification&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Compliance&lt;/strong&gt;: ATSs must be SEC-registered and follow all applicable rules&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Direct P2P&lt;/strong&gt;: Investors cannot trade directly; must go through regulated intermediaries&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reason Code Utilization&lt;/strong&gt;: ATSs should use rejection reason codes to optimize matching&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fee Transparency&lt;/strong&gt;: All broker and RTA fees must be clearly disclosed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern demonstrates how ERC-1450 can support liquid secondary markets through regulated venues while maintaining the strict compliance requirements necessary for security tokens. The existing event structure provides sufficient information for ATSs to facilitate compliant trading without requiring any changes to the core standard.&lt;/p&gt;

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

&lt;h3 id=&quot;why-on-chain-if-the-rta-gates-everything&quot;&gt;Why On-Chain If the RTA Gates Everything?&lt;/h3&gt;

&lt;p&gt;A critical question: If holders cannot initiate transfers and the RTA controls all operations, why use blockchain instead of a traditional centralized database? The answer lies in the unique benefits blockchain provides even within a regulated, controlled environment:&lt;/p&gt;

&lt;h4 id=&quot;1-immutable-global-audit-trail&quot;&gt;1. &lt;strong&gt;Immutable Global Audit Trail&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Unlike traditional databases where entries can be modified or deleted, blockchain provides:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Permanent Record&lt;/strong&gt;: Every mint, burn, and transfer is permanently recorded&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Transparency&lt;/strong&gt;: SEC, FINRA, and state regulators can independently verify all transactions&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Court-Admissible Evidence&lt;/strong&gt;: Immutable records serve as indisputable evidence in legal proceedings&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Real-Time Auditing&lt;/strong&gt;: Eliminates the need for quarterly reconciliations and manual audits&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;2-deterministic-settlement-and-reconciliation&quot;&gt;2. &lt;strong&gt;Deterministic Settlement and Reconciliation&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Traditional securities settlement involves multiple intermediaries and T+2 settlement cycles. ERC-1450 enables:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Instant Settlement&lt;/strong&gt;: Transfers are atomic and final when executed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Failed Trades&lt;/strong&gt;: Eliminates settlement risk and the need for NSCC guarantees&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Automated Reconciliation&lt;/strong&gt;: Cap table is always accurate, no manual reconciliation needed&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reduced Counterparty Risk&lt;/strong&gt;: No need for clearing houses or settlement intermediaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;3-cost-efficiency-through-l2-deployment&quot;&gt;3. &lt;strong&gt;Cost Efficiency Through L2 Deployment&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Deployment on Layer 2 solutions provides dramatic cost savings:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Traditional System&lt;/strong&gt;: $5-50 per transfer through existing infrastructure&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;L2 Deployment&lt;/strong&gt;: $0.01-0.10 per transfer on Base, Arbitrum, or Polygon&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Batch Operations&lt;/strong&gt;: Process hundreds of transfers in a single transaction&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No Infrastructure Costs&lt;/strong&gt;: No need for expensive mainframes and data centers&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;4-programmatic-composability&quot;&gt;4. &lt;strong&gt;Programmatic Composability&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;While direct transfers are disabled, valuable integrations remain:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Portfolio Management&lt;/strong&gt;: Wallets and portfolio trackers can display holdings&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tax Reporting&lt;/strong&gt;: Automated tax lot tracking and 1099 generation&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Regulatory Reporting&lt;/strong&gt;: Automated CAT and Blue Sheet reporting&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Corporate Actions&lt;/strong&gt;: Programmable dividends, splits, and voting&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Compliant Secondary Markets&lt;/strong&gt;: Integration with regulated ATSs and exchanges&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;5-viable-on-chain-integrations&quot;&gt;5. &lt;strong&gt;Viable On-Chain Integrations&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Despite transfer restrictions, these blockchain capabilities remain valuable:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read Operations (Always Available)&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;balanceOf()&lt;/code&gt;: Check holdings&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;totalSupply()&lt;/code&gt;: View outstanding shares&lt;/li&gt;
  &lt;li&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;name()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;symbol()&lt;/code&gt;: Token metadata (OPTIONAL per &lt;a href=&quot;/EIPS/eip-20&quot;&gt;EIP-20&lt;/a&gt;, SHOULD be provided)&lt;/li&gt;
  &lt;li&gt;Event logs: Complete transaction history&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;RTA-Initiated Operations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Automated dividend distributions&lt;/li&gt;
  &lt;li&gt;Programmatic share buybacks&lt;/li&gt;
  &lt;li&gt;Instant corporate actions (splits, mergers)&lt;/li&gt;
  &lt;li&gt;Cross-border settlements without correspondent banking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Compliance Integrations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;KYC/AML oracle integration&lt;/li&gt;
  &lt;li&gt;Accreditation verification services&lt;/li&gt;
  &lt;li&gt;Regulatory reporting automation&lt;/li&gt;
  &lt;li&gt;Smart contract escrows for M&amp;amp;A&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;6-future-interoperability&quot;&gt;6. &lt;strong&gt;Future Interoperability&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Building on blockchain today positions for future innovations:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Central Bank Digital Currencies (CBDCs)&lt;/strong&gt;: Native integration for settlements&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cross-Border Securities&lt;/strong&gt;: Eliminate need for ADRs and dual listings&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;24/7 Markets&lt;/strong&gt;: Enable round-the-clock trading when regulations permit&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;DeFi Integration&lt;/strong&gt;: Future compliant lending and borrowing against securities&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;7-investor-benefits&quot;&gt;7. &lt;strong&gt;Investor Benefits&lt;/strong&gt;&lt;/h4&gt;

&lt;p&gt;Even without direct transfers, investors gain:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Transparency&lt;/strong&gt;: View holdings and transactions in real-time&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Proof of Ownership&lt;/strong&gt;: Cryptographic proof without relying on RTA databases&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Inheritance&lt;/strong&gt;: Simplified estate transfer through smart contracts&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Global Access&lt;/strong&gt;: Hold US securities from anywhere without local custodians&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;the-centralized-database-comparison&quot;&gt;The Centralized Database Comparison&lt;/h4&gt;

&lt;p&gt;A traditional centralized database cannot provide:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Cryptographic Proof&lt;/strong&gt;: No mathematical guarantee of ownership&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Global Accessibility&lt;/strong&gt;: Requires API access and trust&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Auditability&lt;/strong&gt;: Can be modified without trace&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Interoperability&lt;/strong&gt;: Closed system with no composability&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cost Efficiency&lt;/strong&gt;: Requires expensive infrastructure&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Innovation Platform&lt;/strong&gt;: No programmable extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;: ERC-1450 uses blockchain as a &lt;strong&gt;regulated public infrastructure&lt;/strong&gt; rather than a &lt;strong&gt;permissionless payment rail&lt;/strong&gt;. The RTA control model satisfies SEC requirements while capturing blockchain’s benefits: immutability, transparency, cost efficiency, and programmability. This is not about decentralization—it’s about building better market infrastructure.&lt;/p&gt;

&lt;h3 id=&quot;sec-regulatory-framework-for-transfer-agent-operations&quot;&gt;SEC Regulatory Framework for Transfer Agent Operations&lt;/h3&gt;

&lt;p&gt;In the United States securities market, the exclusive control model where only the RTA can execute transfers, mints, and burns is based on established regulatory practice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transfer Agent Exclusive Authority&lt;/strong&gt;: Under SEC Rule 17Ad-1 through 17Ad-22, transfer agents are designated as the sole entities responsible for:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Recording changes in ownership (equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFrom&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Issuing securities (equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mint&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Cancelling securities (equivalent to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;burnFrom&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;Maintaining the official register of security holders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Regulatory Citations&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;17 CFR § 240.17Ad-1&lt;/strong&gt;: Defines transfer agent responsibilities for prompt and accurate clearance and settlement&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;17 CFR § 240.17Ad-10&lt;/strong&gt;: Requires transfer agents to establish adequate internal accounting controls&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;17 CFR § 240.17Ad-11&lt;/strong&gt;: Mandates accurate recordkeeping and reporting systems&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Section 17A of the Securities Exchange Act of 1934&lt;/strong&gt;: Establishes the regulatory framework for transfer agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This standard implements these regulatory requirements by assigning exclusive control of transfer operations to the RTA. While this reflects US market practice rather than a universal requirement, similar designated transfer controller models exist in many jurisdictions worldwide. Implementers in other jurisdictions should consult local regulations for specific requirements.&lt;/p&gt;

&lt;h3 id=&quot;prior-art-and-related-standards&quot;&gt;Prior Art and Related Standards&lt;/h3&gt;

&lt;p&gt;ERC-1450 builds upon lessons learned from previous security token standards:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-884&quot;&gt;ERC-884 (Delaware General Corporations Law (DGCL) compatible share token)&lt;/a&gt; addresses corporate share requirements under Delaware law, focusing on maintaining compliant shareholder registries. While ERC-884 provides important groundwork for regulated securities on blockchain, it explicitly states that broader securities regulation requirements are out of scope.&lt;/p&gt;

&lt;p&gt;Simple Restricted Token Standards provide basic transfer restrictions but do not address critical operational requirements such as recovery mechanisms, court-ordered transfers, or the designated transfer controller model.&lt;/p&gt;

&lt;h3 id=&quot;the-controller-of-record-model&quot;&gt;The Controller of Record Model&lt;/h3&gt;

&lt;p&gt;In the United States, SEC regulations under Rule 17Ad mandate that Registered Transfer Agents maintain exclusive authority over share registry and transfer operations - a “controller of record” model that ensures regulatory compliance and investor protection. While other jurisdictions have similar designated controller requirements with different terminology, the SEC’s RTA framework is particularly stringent and well-established, making it an ideal foundation for this standard that can be adapted to other regulatory environments.&lt;/p&gt;

&lt;p&gt;This standard implements this controller model on-chain, providing:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Single point of regulatory accountability&lt;/li&gt;
  &lt;li&gt;Clear audit trails for compliance&lt;/li&gt;
  &lt;li&gt;Recovery mechanisms for lost assets&lt;/li&gt;
  &lt;li&gt;Court-ordered transfer capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643 (T. rex)&lt;/a&gt; takes a different approach with on-chain identity management and modular compliance rules. While comprehensive, it adds significant complexity through multiple contracts and on-chain identity storage, which raises privacy concerns and gas costs. ERC-3643 is primarily adopted in European markets where regulatory frameworks differ from US SEC requirements.&lt;/p&gt;

&lt;h3 id=&quot;comparison-matrix-security-token-standards&quot;&gt;Comparison Matrix: Security Token Standards&lt;/h3&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;/EIPS/eip-1450&quot;&gt;ERC-1450&lt;/a&gt;&lt;/th&gt;
      &lt;th&gt;&lt;a href=&quot;/EIPS/eip-3643&quot;&gt;ERC-3643&lt;/a&gt; (T. rex)&lt;/th&gt;
      &lt;th&gt;Security Token Suite&lt;/th&gt;
      &lt;th&gt;Standard &lt;a href=&quot;/EIPS/eip-20&quot;&gt;ERC-20&lt;/a&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Control Model&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;RTA-exclusive monopsony&lt;/td&gt;
      &lt;td&gt;Multiple compliance agents&lt;/td&gt;
      &lt;td&gt;Flexible controllers&lt;/td&gt;
      &lt;td&gt;Permissionless&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Identity Management&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Off-chain (privacy-preserving)&lt;/td&gt;
      &lt;td&gt;On-chain identity registry&lt;/td&gt;
      &lt;td&gt;Mixed (implementation-dependent)&lt;/td&gt;
      &lt;td&gt;None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;US SEC Compliance&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Native RTA model&lt;/td&gt;
      &lt;td&gt;❌ Requires adaptation&lt;/td&gt;
      &lt;td&gt;❌ Requires customization&lt;/td&gt;
      &lt;td&gt;❌ Non-compliant&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Privacy&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ No PII on-chain&lt;/td&gt;
      &lt;td&gt;❌ Identity data on-chain&lt;/td&gt;
      &lt;td&gt;⚠️ Implementation varies&lt;/td&gt;
      &lt;td&gt;✅ No identity required&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Gas Efficiency&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Single contract&lt;/td&gt;
      &lt;td&gt;❌ Multiple contracts&lt;/td&gt;
      &lt;td&gt;❌ Modular architecture&lt;/td&gt;
      &lt;td&gt;✅ Minimal&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Operational Complexity&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Simple RTA operations&lt;/td&gt;
      &lt;td&gt;❌ Complex rule engine&lt;/td&gt;
      &lt;td&gt;❌ Partition management&lt;/td&gt;
      &lt;td&gt;✅ Simple transfers&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Recovery Mechanism&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Via controller transfer; optional time-locked workflow&lt;/td&gt;
      &lt;td&gt;⚠️ Implementation-dependent&lt;/td&gt;
      &lt;td&gt;⚠️ Via controller operations&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Court Orders&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Native support&lt;/td&gt;
      &lt;td&gt;⚠️ Via forced transfers&lt;/td&gt;
      &lt;td&gt;✅ Controller operations&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Transfer Restrictions&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ RTA-gated only&lt;/td&gt;
      &lt;td&gt;✅ Rule-based&lt;/td&gt;
      &lt;td&gt;✅ Partition-based&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Direct Transfers&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;❌ Disabled (by design)&lt;/td&gt;
      &lt;td&gt;⚠️ If rules allow&lt;/td&gt;
      &lt;td&gt;⚠️ If authorized&lt;/td&gt;
      &lt;td&gt;✅ Always allowed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Broker Integration&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Native broker model&lt;/td&gt;
      &lt;td&gt;❌ Not specified&lt;/td&gt;
      &lt;td&gt;⚠️ Implementation varies&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Fee Collection&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Built-in mechanism&lt;/td&gt;
      &lt;td&gt;❌ Not specified&lt;/td&gt;
      &lt;td&gt;❌ Not specified&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Existing RTA Infrastructure&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Direct integration&lt;/td&gt;
      &lt;td&gt;❌ Requires middleware&lt;/td&gt;
      &lt;td&gt;❌ Requires adaptation&lt;/td&gt;
      &lt;td&gt;❌ Incompatible&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Regulatory Reporting&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;✅ Clear audit trail&lt;/td&gt;
      &lt;td&gt;✅ On-chain compliance&lt;/td&gt;
      &lt;td&gt;⚠️ Varies by module&lt;/td&gt;
      &lt;td&gt;❌ None&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Market Adoption&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;New (2025)&lt;/td&gt;
      &lt;td&gt;European markets&lt;/td&gt;
      &lt;td&gt;Limited&lt;/td&gt;
      &lt;td&gt;Widespread&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Implementation Complexity&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Low&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
      &lt;td&gt;Low&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;strong&gt;Upgrade Path&lt;/strong&gt;&lt;/td&gt;
      &lt;td&gt;Via RTA Proxy&lt;/td&gt;
      &lt;td&gt;Contract migrations&lt;/td&gt;
      &lt;td&gt;Module updates&lt;/td&gt;
      &lt;td&gt;Immutable&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Key Differentiator&lt;/strong&gt;: ERC-1450’s RTA monopsony model is not a limitation but its core security feature. While other standards offer flexibility, ERC-1450 prioritizes regulatory compliance and operational simplicity through exclusive RTA control—essential for SEC-regulated securities where the transfer agent model is legally mandated.&lt;/p&gt;

&lt;h3 id=&quot;relationship-to-security-token-suites&quot;&gt;Relationship to Security Token Suites&lt;/h3&gt;

&lt;p&gt;Various security token suites provide comprehensive frameworks through multiple complementary standards covering:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Core security token functionality with transfer restrictions&lt;/li&gt;
  &lt;li&gt;Document management for off-chain documents&lt;/li&gt;
  &lt;li&gt;Controller operations for forced transfers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While ERC-1450 appears to overlap with these standards (court-ordered transfers align with controller operations, document references align with document management), we deliberately chose not to extend existing suites for the following reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Philosophical Difference&lt;/strong&gt;: Other security token suites enables flexible, modular compliance where different operators can have different rules. ERC-1450 enforces a single, rigid model where only the RTA has control - essential for SEC compliance and adaptable to similar regulatory models globally. This isn’t a limitation—it’s the core security feature.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Regulatory Alignment&lt;/strong&gt;: Other security token suites was designed for global markets with varying regulations. ERC-1450 is explicitly designed for US SEC-regulated securities with RTA requirements, while providing a framework that other jurisdictions can adopt for their designated transfer controller models. We prioritize regulatory clarity over flexibility.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Simplicity Over Modularity&lt;/strong&gt;: Other security token suites uses multiple interconnected contracts and complex partition logic. ERC-1450 uses a single contract with clear, restricted operations. This reduces attack surface and audit complexity.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;RTA Exclusivity&lt;/strong&gt;: Other security token suites’s controller model allows for multiple controllers or changing controllers. ERC-1450’s RTA model explicitly prevents this—the RTA cannot be changed without cooperative action, protecting against issuer key compromise.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Gas Efficiency&lt;/strong&gt;: By avoiding modular architecture and partition management, ERC-1450 operations are significantly more gas-efficient, important for retail investors on L2s.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Why Not Extend Existing Security Token Standards?&lt;/strong&gt;
Extending existing suites would require supporting their controller models, partition systems, and modular architectures—all of which conflict with the designated transfer controller model used in many regulated securities markets. The approaches are fundamentally incompatible.&lt;/p&gt;

&lt;h3 id=&quot;alignment-with-established-security-token-patterns&quot;&gt;Alignment with Established Security Token Patterns&lt;/h3&gt;

&lt;p&gt;ERC-1450 leverages established security token patterns for maximum interoperability:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller Operations Integration:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Implements standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;controllerTransfer&lt;/code&gt; function for forced transfers&lt;/li&gt;
  &lt;li&gt;Emits standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ControllerTransfer&lt;/code&gt; events that existing tools can index&lt;/li&gt;
  &lt;li&gt;Uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operatorData&lt;/code&gt; parameter to specify transfer type while maintaining standard interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Document Management Integration:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Defines an optional document management interface aligned with established security token patterns: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;removeDocument&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getAllDocuments&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;When implemented, all evidence is stored as document URIs with cryptographic hashes&lt;/li&gt;
  &lt;li&gt;Never stores PII directly on-chain, only references&lt;/li&gt;
  &lt;li&gt;Emits standard &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DocumentUpdated&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DocumentRemoved&lt;/code&gt; events for audit trails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Semantic Clarity Through Data Fields:&lt;/strong&gt;
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;operatorData&lt;/code&gt; parameter in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;controllerTransfer&lt;/code&gt; encodes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Document type (e.g., “COURT_ORDER”, “REGULATORY_ACTION”, “ESTATE_DISTRIBUTION”)&lt;/li&gt;
  &lt;li&gt;Document URI for off-chain storage&lt;/li&gt;
  &lt;li&gt;Cryptographic hash for integrity verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach maintains standard function signatures while preserving the semantic precision required for regulatory compliance.&lt;/p&gt;

&lt;p&gt;ERC-1450 specifically addresses US market needs and SEC requirements by:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Leveraging the existing RTA infrastructure mandated by SEC Rule 17Ad&lt;/li&gt;
  &lt;li&gt;Maintaining investor privacy with off-chain identity management&lt;/li&gt;
  &lt;li&gt;Providing simple, gas-efficient single contract architecture&lt;/li&gt;
  &lt;li&gt;Enabling omnibus custody models used by US broker-dealers&lt;/li&gt;
  &lt;li&gt;Supporting fee-based secondary markets with broker registration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While designed to meet stringent SEC requirements, the standard’s controller model can be adapted to other jurisdictions’ regulatory frameworks that employ similar designated transfer controller models, making it globally applicable while ensuring US regulatory compliance.&lt;/p&gt;

&lt;h3 id=&quot;fractional-shares-support&quot;&gt;Fractional Shares Support&lt;/h3&gt;

&lt;p&gt;Unlike earlier proposals that forced &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;decimals()&lt;/code&gt; to return 0, ERC-1450 allows configurable decimal places set at deployment. This flexibility recognizes that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Modern Markets Support Fractions&lt;/strong&gt;: Many securities now trade in fractional amounts:
    &lt;ul&gt;
      &lt;li&gt;Mutual funds and ETFs often have fractional shares&lt;/li&gt;
      &lt;li&gt;REITs frequently allow fractional ownership&lt;/li&gt;
      &lt;li&gt;Modern broker-dealers offer fractional share trading for retail investors&lt;/li&gt;
      &lt;li&gt;Dividend reinvestment plans (DRIPs) create fractional shares&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Immutable at Deployment&lt;/strong&gt;: The decimal places are set once at contract creation and cannot be changed, ensuring consistency throughout the security’s lifecycle.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;RTA Control Maintained&lt;/strong&gt;: Whether whole or fractional, all transfers remain under exclusive RTA control, maintaining regulatory compliance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This design allows issuers to choose the appropriate divisibility for their specific security type while maintaining the strict RTA control model.&lt;/p&gt;

&lt;h3 id=&quot;wallet-and-dex-integration-via-erc-165&quot;&gt;Wallet and DEX Integration via ERC-165&lt;/h3&gt;

&lt;p&gt;ERC-1450 implements ERC-165 introspection to prevent broken user experiences in wallets, DEXs, and other tools that expect standard ERC-20 behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Detection Flow for Integrators:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 1. Check if it&apos;s a security token (quickest check)
&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;token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isSecurityToken&lt;/span&gt;&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;// This is ERC-1450, disable transfer/approve UI
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handleSecurityToken&lt;/span&gt;&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;// 2. Alternative: Check via ERC-165
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1450_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;computed_interface_id&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;token&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;IERC1450_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;c1&quot;&gt;// This is ERC-1450, handle accordingly
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handleSecurityToken&lt;/span&gt;&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;// 3. For maximum compatibility, also check:
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC20_ID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x36372b07&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;isERC20&lt;/span&gt; &lt;span class=&quot;o&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;supportsInterface&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IERC20_ID&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;isSecure&lt;/span&gt; &lt;span class=&quot;o&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;isSecurityToken&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;isERC20&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isSecure&lt;/span&gt;&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;// Restricted ERC-20 interface detected
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;showRestrictedTokenUI&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;Expected Wallet/DEX Behavior:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Display&lt;/strong&gt;: Show token balances normally (read-only operations work)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Transfers&lt;/strong&gt;: Hide or disable transfer/send buttons&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Swaps&lt;/strong&gt;: Exclude from DEX trading interfaces&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Approvals&lt;/strong&gt;: Hide or disable approval interfaces&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Information&lt;/strong&gt;: Display “Security Token - Transfers Restricted” or similar&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Secondary Market&lt;/strong&gt;: Optionally provide link to compliant secondary market&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This introspection mechanism ensures that:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Wallets don’t show broken transfer interfaces&lt;/li&gt;
  &lt;li&gt;DEXs don’t attempt to list restricted tokens&lt;/li&gt;
  &lt;li&gt;Portfolio trackers can display holdings correctly&lt;/li&gt;
  &lt;li&gt;Users understand the token’s restricted nature&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optional: ERC-1820 Registry&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For broader discovery, implementations MAY also register with the &lt;a href=&quot;/EIPS/eip-1820&quot;&gt;ERC-1820 Pseudo-introspection Registry&lt;/a&gt;. This allows any address (including externally owned accounts acting as proxies) to publish interface support:&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;// Optional ERC-1820 registration
&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;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IERC1450_HASH&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;IERC1450Token&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setInterfaceImplementer&lt;/span&gt;&lt;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;IERC1450_HASH&lt;/span&gt;&lt;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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, ERC-165 support is sufficient for most use cases and is simpler to implement.&lt;/p&gt;

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

&lt;p&gt;ERC-1450 implements the ERC-20 interface but with critical behavioral differences. Per the &lt;a href=&quot;/EIPS/eip-20#specification&quot;&gt;ERC-20 specification&lt;/a&gt;, functions MAY return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert()&lt;/code&gt; on failure. The specification notes: “Callers MUST handle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;returns (bool)&lt;/code&gt;. Callers MUST NOT assume that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt; is never returned!”&lt;/p&gt;

&lt;p&gt;This standard is ABI-compatible with ERC-20 for reads; state-changing ERC-20 flows are disallowed by design. Contracts MUST implement ERC-165 and expose the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC1450&lt;/code&gt; interface ID so clients can detect restricted semantics before offering send/approve UI. Note that ERC-20 itself does not define ERC-165 detection; using ERC-165 for ERC-20 interface detection is acceptable but not universally supported. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSecurityToken()&lt;/code&gt; helper function provides an additional discovery mechanism, though ERC-165 and ERC-1820 should be considered the primary discovery methods.&lt;/p&gt;

&lt;p&gt;ERC-1450 makes the following deliberate choices:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read-Only Functions (Fully Compatible):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function totalSupply() external view returns (uint256)&lt;/code&gt;&lt;/strong&gt; - Works normally&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function balanceOf(address account) external view returns (uint256)&lt;/code&gt;&lt;/strong&gt; - Works normally&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function allowance(address owner, address spender) external view returns (uint256)&lt;/code&gt;&lt;/strong&gt; - MUST always return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Restricted Functions (Modified Behavior):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function transfer(address to, uint256 amount) external returns (bool)&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function approve(address spender, uint256 amount) external returns (bool)&lt;/code&gt;&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;MUST always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt;&lt;/strong&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC1450TransferDisabled&lt;/code&gt; error (never return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;This is permitted by ERC-20 which allows revert as a failure mode&lt;/li&gt;
      &lt;li&gt;Holder-initiated transfers are not legal for regulated securities&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;function transferFrom(address from, address to, uint256 amount) external returns (bool)&lt;/code&gt;&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;MUST always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;revert&lt;/code&gt;&lt;/strong&gt; with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ERC1450TransferDisabled&lt;/code&gt; error (never return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;This standard ERC-20 function is disabled to prevent confusion&lt;/li&gt;
      &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferFromRegulated()&lt;/code&gt; for actual transfers with regulation tracking&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Critical for Integrators&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Implementers MUST expose ERC-165 interface IDs&lt;/strong&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isSecurityToken&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;This allows clients to detect non-standard ERC-20 behavior before attempting transfers&lt;/li&gt;
      &lt;li&gt;Without this detection, wallets and DEXs would mis-assume standard ERC-20 semantics&lt;/li&gt;
      &lt;li&gt;The interface detection prevents users from attempting operations that will always fail&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Approval&lt;/code&gt; event&lt;/strong&gt;:
    &lt;ul&gt;
      &lt;li&gt;Will never be emitted as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve()&lt;/code&gt; always reverts&lt;/li&gt;
      &lt;li&gt;Implementations MAY omit this event entirely&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Test cases are provided in the reference implementation repository (see Reference Implementation section).&lt;/p&gt;

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

&lt;p&gt;A production-ready reference implementation is available at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github.com/StartEngine/erc1450-reference&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This implementation has completed a comprehensive security audit by &lt;strong&gt;Halborn Security&lt;/strong&gt; (December 2025) with all findings addressed. See the repository for full audit report and remediation details.&lt;/p&gt;

&lt;p&gt;The reference implementation includes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Full ERC-1450 compliant token contract&lt;/li&gt;
  &lt;li&gt;RTA Proxy pattern for enhanced security&lt;/li&gt;
  &lt;li&gt;Comprehensive test suite covering all functionality&lt;/li&gt;
  &lt;li&gt;Deployment scripts and integration examples&lt;/li&gt;
  &lt;li&gt;Gas optimization benchmarks&lt;/li&gt;
  &lt;li&gt;Contract versioning with automatic sync from package.json&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Key features demonstrated in the reference implementation:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Transfer request workflow with fee collection&lt;/li&gt;
  &lt;li&gt;Recovery mechanism with timelock security&lt;/li&gt;
  &lt;li&gt;Court-ordered transfers and recovery procedures&lt;/li&gt;
  &lt;li&gt;Integration with existing ERC-20 infrastructure&lt;/li&gt;
  &lt;li&gt;Version tracking for upgrade detection&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;contract-versioning&quot;&gt;Contract Versioning&lt;/h3&gt;

&lt;p&gt;The reference implementation includes automatic version synchronization between the npm package version and the contract &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;version()&lt;/code&gt; function. This enables:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Upgrade Detection&lt;/strong&gt;: Compare deployed contract version against local artifacts to detect available upgrades&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Audit Trail&lt;/strong&gt;: Know exactly which version was deployed at any given time&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bytecode Verification&lt;/strong&gt;: Match deployed bytecode hash against expected hash for security verification&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;c1&quot;&gt;// Query version from deployed contract
&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;deployedVersion&lt;/span&gt; &lt;span class=&quot;o&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;version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;// Returns &quot;1.17.0&quot;
&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Compare with local artifacts to detect upgrades
&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;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;deployedVersion&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;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;localVersion&lt;/span&gt;&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;// Upgrade available
&lt;/span&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 version is automatically synced via a pre-commit hook, ensuring the contract version always matches the package version without manual updates.&lt;/p&gt;

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

&lt;h3 id=&quot;key-management-and-custody&quot;&gt;Key Management and Custody&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Investor Private Key Loss&lt;/strong&gt;:
When investors lose access to their private keys, the RTA’s exclusive control over transfers enables recovery procedures. Unlike permissionless tokens where lost keys mean permanently lost assets, ERC-1450’s RTA can execute court-ordered recovery transfers from lost addresses to new investor-controlled addresses after proper legal verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transfer Agent Key Security&lt;/strong&gt;:
The RTA MUST implement institutional-grade key management including:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Hardware Security Modules (HSMs) or secure custody solutions (e.g., Fireblocks)&lt;/li&gt;
  &lt;li&gt;Multi-signature requirements for critical operations&lt;/li&gt;
  &lt;li&gt;Key rotation procedures through the RTAProxy pattern&lt;/li&gt;
  &lt;li&gt;Geographically distributed key shards to prevent single points of failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Issuer Key Compromise&lt;/strong&gt;:
The RTAProxy pattern protects against compromised issuer keys by preventing unauthorized RTA changes. Once the RTAProxy is set as the transfer agent, even a compromised issuer cannot redirect token control to an attacker.&lt;/p&gt;

&lt;h3 id=&quot;rta-control-model-rationale&quot;&gt;RTA Control Model Rationale&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why the Transfer Controller Has Unilateral Control&lt;/strong&gt;:
The design decision to give the designated transfer controller exclusive control over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;changeIssuer&lt;/code&gt; (preventing even the issuer from changing the issuer address themselves) is intentional and based on operational requirements:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Regulatory Independence in US Markets&lt;/strong&gt;: In the United States, SEC Rule 17Ad-10 requires transfer agents to establish and maintain adequate internal accounting controls. SEC Rule 17Ad-11 mandates accurate recordkeeping. Transfer agents have fiduciary duties to shareholders that must remain independent from issuer influence. While other jurisdictions may have different requirements, this standard implements the US model which can be adapted for other regulatory frameworks.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Security Through Regulation&lt;/strong&gt;: In US markets, RTAs are heavily regulated entities with:
    &lt;ul&gt;
      &lt;li&gt;SEC registration under Section 17A of the Securities Exchange Act&lt;/li&gt;
      &lt;li&gt;Compliance with Rules 17Ad-1 through 17Ad-22&lt;/li&gt;
      &lt;li&gt;Regular FINRA examinations under Rule 17Ad-13&lt;/li&gt;
      &lt;li&gt;Statutory liability for failures&lt;/li&gt;
      &lt;li&gt;Professional insurance requirements&lt;/li&gt;
      &lt;li&gt;Established business continuity plans&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Issuer Key Vulnerability&lt;/strong&gt;: Issuers (often startups) typically lack institutional-grade key management. If an issuer’s keys are compromised and they could change the RTA, an attacker could:
    &lt;ul&gt;
      &lt;li&gt;Replace the legitimate RTA with their own address&lt;/li&gt;
      &lt;li&gt;Steal all tokens from investors&lt;/li&gt;
      &lt;li&gt;Destroy the entire cap table&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Legitimate RTA Changes Are Supported&lt;/strong&gt;: The model does support changing RTAs through cooperative action:
    &lt;ul&gt;
      &lt;li&gt;Current RTA and issuer negotiate transition&lt;/li&gt;
      &lt;li&gt;Legal agreements are executed off-chain&lt;/li&gt;
      &lt;li&gt;Current RTA initiates the technical handoff&lt;/li&gt;
      &lt;li&gt;New RTA accepts responsibility&lt;/li&gt;
      &lt;li&gt;This mirrors traditional RTA transitions in conventional securities&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Alternative Models Considered&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Dual-control&lt;/strong&gt;: Would violate SEC Rule 17Ad requirements for RTA independence&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Time-locks&lt;/strong&gt;: Could prevent emergency actions required by court orders&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Multi-sig with issuer&lt;/strong&gt;: Reintroduces issuer key compromise risk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This design prioritizes regulatory compliance and investor protection over decentralization. For fully decentralized governance tokens, other standards like ERC-20 remain more appropriate.&lt;/p&gt;

&lt;h3 id=&quot;smart-contract-security&quot;&gt;Smart Contract Security&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Reentrancy Protection&lt;/strong&gt;:
All state changes MUST occur before external calls. The restricted nature of ERC-1450 (direct value movement disabled, all transfers require RTA execution) naturally limits reentrancy vectors, but implementations should still follow check-effects-interactions patterns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Integer Overflow/Underflow&lt;/strong&gt;:
Solidity 0.8.x provides automatic overflow protection. Implementations using earlier versions MUST use SafeMath or equivalent libraries for all arithmetic operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authorization Bypasses&lt;/strong&gt;:
Critical functions are protected by modifiers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onlyTransferAgent&lt;/code&gt;). Implementations MUST ensure:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Modifiers check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; against stored RTA address&lt;/li&gt;
  &lt;li&gt;No functions exist that bypass RTA authorization&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve()&lt;/code&gt; functions must ALWAYS revert with appropriate &lt;a href=&quot;/EIPS/eip-6093&quot;&gt;ERC-6093&lt;/a&gt; errors&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;regulatory-compliance-risks&quot;&gt;Regulatory Compliance Risks&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Unauthorized Transfers&lt;/strong&gt;:
The disabled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; function prevents investors from bypassing KYC/AML requirements. All transfers must go through the RTA, ensuring regulatory compliance for every transaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sanctions Screening&lt;/strong&gt;:
The RTA MUST maintain updated sanctions lists and check all parties before executing transfers. The exclusive RTA control ensures no transfers can bypass these checks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jurisdiction Restrictions&lt;/strong&gt;:
Securities often have geographic restrictions. The RTA enforces these through off-chain verification before executing any transfer.&lt;/p&gt;

&lt;h3 id=&quot;off-chain-infrastructure-security&quot;&gt;Off-Chain Infrastructure Security&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Database Compromise&lt;/strong&gt;:
As mentioned in the specification, RTAs maintain off-chain databases of investor information. These systems MUST implement:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Encryption at rest and in transit&lt;/li&gt;
  &lt;li&gt;Regular security audits&lt;/li&gt;
  &lt;li&gt;Access controls and audit logging&lt;/li&gt;
  &lt;li&gt;Backup and recovery procedures&lt;/li&gt;
  &lt;li&gt;Data residency compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Oracle Risks&lt;/strong&gt;:
If the implementation relies on oracles for pricing or other data:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Multiple oracle sources should be used to prevent manipulation&lt;/li&gt;
  &lt;li&gt;Circuit breakers should halt operations on suspicious data&lt;/li&gt;
  &lt;li&gt;Time delays for critical operations based on oracle data&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;denial-of-service-risks&quot;&gt;Denial-of-Service Risks&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;RTA Availability&lt;/strong&gt;:
The RTA being the sole transfer authority creates a potential bottleneck. Mitigations include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;High-availability infrastructure with redundancy&lt;/li&gt;
  &lt;li&gt;Service Level Agreements (SLAs) for uptime&lt;/li&gt;
  &lt;li&gt;Batch processing capabilities to handle high volumes&lt;/li&gt;
  &lt;li&gt;Emergency procedures for RTA unavailability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gas Griefing&lt;/strong&gt;:
Batch operations should implement gas limits per operation to prevent one failed transfer from reverting an entire batch.&lt;/p&gt;

&lt;h3 id=&quot;defi-integration-risks&quot;&gt;DeFi Integration Risks&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Incompatibility with DEXs&lt;/strong&gt;:
ERC-1450 tokens cannot be traded on standard DEXs due to disabled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;approve()&lt;/code&gt; functions. This is intentional for regulatory compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wrapper Contract Risks&lt;/strong&gt;:
Any wrapper contracts that attempt to make ERC-1450 tokens tradeable MUST be carefully audited as they could bypass regulatory controls. The RTA should monitor for and potentially restrict transfers to unauthorized wrapper contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flash Loan Attacks&lt;/strong&gt;:
The disabled &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transfer()&lt;/code&gt; function prevents flash loan attacks. However, any future extensions should carefully consider flash loan implications.&lt;/p&gt;

&lt;h3 id=&quot;upgrade-and-migration-security&quot;&gt;Upgrade and Migration Security&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Upgrade Authority&lt;/strong&gt;:
If the implementation uses upgradeable proxy patterns, upgrade authority MUST be carefully controlled, potentially requiring both RTA and issuer approval.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Migration Procedures&lt;/strong&gt;:
Token migrations to new contracts should include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Snapshot mechanisms to preserve balances&lt;/li&gt;
  &lt;li&gt;Time-locked migration periods&lt;/li&gt;
  &lt;li&gt;Rollback capabilities in case of issues&lt;/li&gt;
  &lt;li&gt;Clear communication to all stakeholders&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;emergency-response&quot;&gt;Emergency Response&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Circuit Breakers&lt;/strong&gt;:
Implementations should include emergency pause mechanisms that can be triggered by the RTA in case of:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Smart contract vulnerabilities discovered&lt;/li&gt;
  &lt;li&gt;Regulatory enforcement actions&lt;/li&gt;
  &lt;li&gt;Custody provider compromises&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Incident Response Plan&lt;/strong&gt;:
RTAs must maintain documented procedures for:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Key compromise scenarios&lt;/li&gt;
  &lt;li&gt;Smart contract vulnerabilities&lt;/li&gt;
  &lt;li&gt;Regulatory interventions&lt;/li&gt;
  &lt;li&gt;System outages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These security considerations are informed by operational experience from SEC-registered transfer agents managing billions in compliant securities offerings. The restricted nature of ERC-1450, while limiting functionality compared to permissionless tokens, provides strong security guarantees essential for regulatory compliance and investor protection.&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, 25 Sep 2018 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-1450</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-1450</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Atomic Swap-based American Call Option Contract Standard</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #2266 - Atomic Swap-based American Call Option Contract Standard&lt;/strong&gt; is in Last Call status. It is authored by Runchao Han &lt;runchao.han@monash.edu&gt;, Haoyu Lin &lt;chris.haoyul@gmail.com&gt;, Jiangshan Yu &lt;jiangshan.yu@monash.edu&gt; and was originally created 2019-08-17. It is in the ERC category of type Standards Track. Please review and note any changes that should block acceptance.&lt;/p&gt;
        
          &lt;p&gt;The author has requested that discussions happen at the following URL: &lt;a href=&quot;https://github.com/ethereum/EIPs/issues/2266&quot;&gt;https://github.com/ethereum/EIPs/issues/2266&lt;/a&gt;&lt;/p&gt;
        
        &lt;hr /&gt;
        &lt;h2 id=&quot;simple-summary&quot;&gt;Simple Summary&lt;/h2&gt;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

&lt;p&gt;This standard introduces a flexible on-chain storage pattern that organizes data into structured tables that consist of records with fixed key and value schemas, similar to a traditional database. This storage pattern consists of a unified contract interface for data access, along with a compact binary encoding format for both static and dynamic data types. State changes are tracked through standardized events that enable automatic, schema-aware state replication by off-chain indexers. New tables can be dynamically registered at runtime through a special table that stores schema metadata for all tables, allowing the system to evolve without breaking existing contracts or integrations.&lt;/p&gt;

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

&lt;p&gt;The absence of consistent standards for on-chain data management in smart contracts can lead to rigid implementations, tightly coupled contract logic with off-chain services, and challenges in updating or extending a contract’s data layout without breaking existing integrations.&lt;/p&gt;

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

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Automatic Indexing&lt;/strong&gt;: By emitting consistent, standardized events during state changes, off-chain services can automatically track on-chain state and provide schema-aware indexer APIs.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Elimination of Custom Getter Functions&lt;/strong&gt;: Any contract or off-chain service can read stored data through a consistent interface, decoupling smart contract implementation from specific data access patterns and reducing development overhead.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Simpler Upgradability&lt;/strong&gt;: This pattern leverages unstructured storage, making it easier to upgrade contract logic without the risks associated with using a fixed storage layout.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Flexible Data Extensions&lt;/strong&gt;: New tables can be added at runtime without without breaking existing integrations with other data consumers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Reduced gas costs&lt;/strong&gt;: Using efficient data packing reduces gas costs for both storage and event emissions.&lt;/li&gt;
&lt;/ol&gt;

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

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

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

&lt;p&gt;A smart contract that implements the interface proposed by this ERC and organizes data in Tables. It emits events for each data operation so that off-chain components can replicate the state of all tables.&lt;/p&gt;

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

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

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

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

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

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

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

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

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

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Bytes (from left to right)&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Table type identifier&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2-31&lt;/td&gt;
      &lt;td&gt;Unique identifier&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Table Type Identifiers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x7462&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;tb&quot;&lt;/code&gt;) for on-chain tables&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x6f74&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;ot&quot;&lt;/code&gt;) for off-chain tables&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;schema&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Used to represent the layout of Records within a table.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Schema&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Each Table defines two schemas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key Schema: the types of the keys used to uniquely identify a &lt;strong&gt;Record&lt;/strong&gt; within a table. It consists only of fixed-length data types.&lt;/li&gt;
  &lt;li&gt;Value Schema: the types of the value fields of a &lt;strong&gt;Record&lt;/strong&gt; within a table, which can include both fixed-length and variable-length data types.&lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Byte(s) from left to right&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Constraint&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Total byte length of static fields&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Number of static length fields&lt;/td&gt;
      &lt;td&gt;≤ (28 - number of dynamic length fields)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Number of dynamic length fields&lt;/td&gt;
      &lt;td&gt;For the key schema, 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;For the value schema, ≤5&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4-31&lt;/td&gt;
      &lt;td&gt;Each byte encodes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Dynamic-length types MUST come after all the static-length types.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;schematype&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Single byte that represents the type of a specific static or dynamic field.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SchemaType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;type-encoding&quot;&gt;Type Encoding&lt;/h5&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Value Range&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x1F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt; (increments of 8 bits)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x20&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x3F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int8&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256&lt;/code&gt; (increments of 8 bits)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x40&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x5F&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes1&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x60&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x61&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x62&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x81&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x82&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xA1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int8[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;int256[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xA2&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC1&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes1[]&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC2&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bool[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address[]&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC4&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0xC5&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;fieldlayout&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Encodes the concrete value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; information, specifically the total byte length of the static fields, the number of dynamic fields and the length of each static field on its own.&lt;/p&gt;

&lt;p&gt;This encoding serves as an optimization for on-chain operations. By having the exact lengths readily available, the Store doesn’t need to repeatedly compute or translate the schema definitions into actual field lengths during execution.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FieldLayout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Byte(s) from left to right&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Constraint&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0-1&lt;/td&gt;
      &lt;td&gt;Total length of static fields&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Number of static length fields&lt;/td&gt;
      &lt;td&gt;≤ (28 - number of dynamic length fields)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Number of dynamic length fields&lt;/td&gt;
      &lt;td&gt;For the key schema, 0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;For the value schema, ≤5&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4-31&lt;/td&gt;
      &lt;td&gt;Each byte encodes the byte length of the corresponding static field&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;encodedlengths&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Encodes the byte length of all the dynamic fields of a specific Record. It is returned by the Store methods when reading a Record, as it is needed for decoding dynamic fields.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Bytes (from least to most significant)&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0x00-0x06&lt;/td&gt;
      &lt;td&gt;uint56&lt;/td&gt;
      &lt;td&gt;Total byte length of dynamic data&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x07-0xB&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the first dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x0C-0x10&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the second dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x11-0x15&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the third dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x16-0x1A&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the fourth dynamic field&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0x1B-0x1F&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;Length of the fifth dynamic field&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;packed-data-encoding&quot;&gt;Packed Data Encoding&lt;/h3&gt;

&lt;p&gt;Record data returned by Store methods and included in Store events uses the following encoding rules.&lt;/p&gt;

&lt;h4 id=&quot;field-limits&quot;&gt;Field Limits&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Maximum Total Fields&lt;/strong&gt;: A record can contain up to &lt;strong&gt;28 fields&lt;/strong&gt; in total (both static and dynamic fields combined).
    &lt;ul&gt;
      &lt;li&gt;This limit is due to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; type structure, which uses 28 bytes (bytes 4 to 31) to define field types, with one byte per field (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Dynamic Fields Limit&lt;/strong&gt;: A record can have up to &lt;strong&gt;5 dynamic fields&lt;/strong&gt;.
    &lt;ul&gt;
      &lt;li&gt;This is due to the fact that a single 32 bytes word (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;) to encode the byte lengths of each dynamic field, instead of encoding each length separately as Solidity’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abi.encode&lt;/code&gt; would.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Static Fields Limit&lt;/strong&gt;: The maximum number of static fields is &lt;strong&gt;28 minus the number of dynamic fields&lt;/strong&gt;.
    &lt;ul&gt;
      &lt;li&gt;For example, if there are 5 dynamic fields, the maximum number of static fields is 23 (28 - 5).&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;encoding-rules&quot;&gt;Encoding Rules&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;Static-length fields are encoded without any padding, and concatenated in the order they are defined in the schema, which is equivalent to using Solidity’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abi.encodePacked&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;For dynamic-length fields (arrays, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;s):
    &lt;ul&gt;
      &lt;li&gt;If the field is an array, its elements are tightly packed without padding.&lt;/li&gt;
      &lt;li&gt;All dynamic fields are concatenated together without padding and without including their lengths.&lt;/li&gt;
      &lt;li&gt;The lengths of all dynamic fields are encoded into a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EncodedLengths&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;example&quot;&gt;Example&lt;/h4&gt;

&lt;p&gt;Suppose a table has the following value schema:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Encoding (Pseudocode)&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;owner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// This is a custom function as Solidity does not provide a way to tightly pack array elements
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packedScores&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packElementsWithoutPadding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// abi.encodePacked concatenates both description and packedScores without including their lengths
&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;abi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodePacked&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;packedScores&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Total length is encoded in the 56 least significant bits
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Each length is encoded using 5 bytes
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encodedData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The full encoded record data is represented by the following tuple:
// (staticData, encodedLengths, dynamicData)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;store-interface&quot;&gt;Store Interface&lt;/h3&gt;

&lt;p&gt;All Stores MUST implement the following interface.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IStore&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/**
   * Get full encoded record (all fields, static and dynamic data) for the given tableId and key tuple.
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/**
   * Get a single encoded field from the given tableId and key tuple.
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;calldata&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldIndex&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;cm&quot;&gt;/**
   * Get the byte length of a single field from the given tableId and key tuple
   */&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getFieldLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldIndex&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;external&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;returns&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;uint256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The return values of both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt; use the encoding rules previously defined in the Packed Data Encoding section. More specifically, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt; returns the fully encoded record tuple, and the data returned by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt; is encoded using the encoding rules as if the field was being encoded on its own.&lt;/p&gt;

&lt;h3 id=&quot;store-operations-and-events&quot;&gt;Store Operations and Events&lt;/h3&gt;

&lt;p&gt;This standard defines three core operations for manipulating records in a table: setting, updating, and deleting. For each operation, specific events must be emitted. The implementation details of these operations are left to the discretion of each Store implementation.&lt;/p&gt;

&lt;p&gt;The fundamental requirement is that for on-chain tables the Record data retrieved through the Store interface methods at any given block MUST be consistent with the Record data that would be obtained by applying the operations implied by the Store events up to that block. This ensures data integrity and allows for accurate off-chain state reconstruction.&lt;/p&gt;

&lt;h4 id=&quot;store_setrecord&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Setting a Record means overwriting all of its fields. This operation can be performed whether the record has been set before or not (the standard does not enforce existence checks).&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event &lt;strong&gt;MUST&lt;/strong&gt; be emitted whenever the full data of a record has been overwritten.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SetRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicData&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the record is set&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;staticData&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The static data of the record using packed encoding&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;encodedLengths&lt;/td&gt;
      &lt;td&gt;EncodedLengths&lt;/td&gt;
      &lt;td&gt;The encoded lengths of the dynamic data of the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dynamicData&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The dynamic data of the record, using &lt;a href=&quot;#packed-data-encoding&quot;&gt;custom packed encoding&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_splicestaticdata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Splicing the static data of a Record consists in overwriting bytes of the packed encoded static fields. The total length of static data does not change as it is determined by the table’s value schema.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt; event MUST be emitted whenever the static data of the Record has been spliced.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SpliceStaticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint48&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the data is spliced&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;start&lt;/td&gt;
      &lt;td&gt;uint48&lt;/td&gt;
      &lt;td&gt;The start position in bytes for the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;data&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;Packed ABI encoding of a tuple with the value’s static fields&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_splicedynamicdata&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Splicing the dynamic data of a Record involves modifying the packed encoded representation of its dynamic fields by removing, replacing, and/or inserting new bytes in place.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt; event MUST be emitted whenever the dynamic data of the Record has been spliced.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_SpliceDynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dynamicFieldIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint48&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;uint40&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deleteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;EncodedLengths&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;bytes&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the data is spliced&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dynamicFieldIndex&lt;/td&gt;
      &lt;td&gt;uint8&lt;/td&gt;
      &lt;td&gt;The index of the dynamic field to splice data, relative to the start of the dynamic fields (Dynamic field index = field index - number of static fields)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;start&lt;/td&gt;
      &lt;td&gt;uint48&lt;/td&gt;
      &lt;td&gt;The start position in bytes for the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;deleteCount&lt;/td&gt;
      &lt;td&gt;uint40&lt;/td&gt;
      &lt;td&gt;The number of bytes to delete in the splice operation&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;encodedLengths&lt;/td&gt;
      &lt;td&gt;EncodedLengths&lt;/td&gt;
      &lt;td&gt;The resulting encoded lengths of the dynamic data of the record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;data&lt;/td&gt;
      &lt;td&gt;bytes&lt;/td&gt;
      &lt;td&gt;The data to insert into the dynamic data of the record at the start byte&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h4 id=&quot;store_deleterecord&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_DeleteRecord&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_DeleteRecord&lt;/code&gt; event MUST be emitted whenever the Record has been deleted from the Table.&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Store_DeleteRecord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;indexed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bytes32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Parameters:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;strong&gt;Name&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
      &lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;tableId&lt;/td&gt;
      &lt;td&gt;ResourceId&lt;/td&gt;
      &lt;td&gt;The ID of the table where the record is deleted&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;keyTuple&lt;/td&gt;
      &lt;td&gt;bytes32[]&lt;/td&gt;
      &lt;td&gt;An array representing the composite key for the record&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;See the &lt;a href=&quot;#reference-implementation&quot;&gt;reference implementation section&lt;/a&gt; for an example on how to index store events.&lt;/p&gt;

&lt;h3 id=&quot;the-tables-table&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table&lt;/h3&gt;

&lt;p&gt;To keep track of the information of each table and support registering new tables at runtime, the Store implementation MUST include a special on-chain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table, which behaves the same way as other on-chain tables except for the special constraints mentioned below.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table MUST use the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;s:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key Schema:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tableId&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt;): &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt; of the table this record describes.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Value Schema:
    &lt;ul&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fieldLayout&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt;): encodes the byte length of each static data type in the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;keySchema&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;): represents the data types of the (composite) key of the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;valueSchema&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt;): represents the data types of the value fields of the table.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abiEncodedKeyNames&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;): ABI encoded string array of key names.&lt;/li&gt;
      &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abiEncodedFieldNames&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;): ABI encoded string array of field names.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Records stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table are considered immutable:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; MUST emit a single &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event for each table being registered.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; SHOULD NOT emit any other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store&lt;/code&gt; events for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Table&lt;/code&gt; registered in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table MUST store a record that describes itself before any other table is registered, emitting the corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event. The record must use the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tableId&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-solidity highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// First two bytes indicates that this is an on-chain table
// The next 30 bytes are the unique identifier for the Tables table
// bytes32(&quot;tb&quot;) | bytes32(&quot;store&quot;) &amp;gt;&amp;gt; (2 * 8) | bytes32(&quot;Tables&quot;) &amp;gt;&amp;gt; (2 * 8 + 14 * 8)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tableId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ResourceId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x746273746f72650000000000000000005461626c657300000000000000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By using a predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResourceId&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Schema&lt;/code&gt; for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table, off-chain indexers can interpret store events for all registered tables. This enables the development of advanced off-chain services that operate on structured data rather than raw encoded data like in the previous indexer implementation example.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;splice-events&quot;&gt;Splice Events&lt;/h3&gt;

&lt;p&gt;While the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SetRecord&lt;/code&gt; event suffices for tracking the data of each record off-chain, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Splice&lt;/code&gt; events (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceStaticData&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Store_SpliceDynamicData&lt;/code&gt;) allows for more efficient partial updates. When only a portion of a record changes, emitting a full &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetRecord&lt;/code&gt; event would be inefficient because the entire record data would need to be read from storage and emitted. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Splice&lt;/code&gt; events enable the store to emit only the minimal necessary data for the update, reducing gas consumption. This is particularly important for records with large dynamic fields, as the cost of updating them doesn’t grow with the field’s size.&lt;/p&gt;

&lt;h3 id=&quot;disallowing-arrays-of-dynamic-types&quot;&gt;Disallowing Arrays of Dynamic Types&lt;/h3&gt;

&lt;p&gt;Arrays of dynamic types (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string[]&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes[]&lt;/code&gt;) are intentionally not included as supported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SchemaType&lt;/code&gt;s. This restriction enforces a flat data schema, which simplifies the store implementation and enhances efficiency. If users need to store such data structures, they can model them using a separate table with a schema like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{ index: uint256, data: bytes }&lt;/code&gt;, where each array element is represented as an individual record.&lt;/p&gt;

&lt;h3 id=&quot;fieldlayout-optimization&quot;&gt;FieldLayout Optimization&lt;/h3&gt;

&lt;p&gt;Including the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FieldLayout&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; schema provides an on-chain optimization by precomputing and storing the exact byte lengths of static fields. This eliminates the need to repeatedly compute field lengths and offsets during runtime, which can be gas-intensive. By having this information readily available, the store can perform storage operations more efficiently, while components reading from the store can retrieve it from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table to decode the corresponding records.&lt;/p&gt;

&lt;h3 id=&quot;special-tables-table&quot;&gt;Special &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table&lt;/h3&gt;

&lt;p&gt;Including a special &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tables&lt;/code&gt; table provides significant benefits for off-chain indexers. While emitting events for table registration isn’t strictly necessary for basic indexers that operate on raw encoded data, doing so makes indexers aware of the schemas used by each table. This awareness enables the development of more advanced, schema-aware indexer APIs (e.g., SQL-like query capabilities), enhancing the utility and flexibility of off-chain data interactions.&lt;/p&gt;

&lt;p&gt;By reusing existing Store abstractions for table registration, we also simplify the implementation and eliminate the need for additional, specific table registration events. Indexers can leverage the standard Store events to access schema information, ensuring consistency and reducing complexity.&lt;/p&gt;

&lt;h2 id=&quot;reference-implementation&quot;&gt;Reference Implementation&lt;/h2&gt;

&lt;h3 id=&quot;store-event-indexing&quot;&gt;Store Event Indexing&lt;/h3&gt;

&lt;p&gt;The following example shows how a simple in-memory indexer can use the Store events to replicate the Store state off-chain. It is important to note that this indexer operates over raw encoded data which is not that useful on its own, but can be improved as we will explain in the next section.&lt;/p&gt;

&lt;p&gt;We use TypeScript for this example but it can easily be replicated with other languages.&lt;/p&gt;

&lt;div class=&quot;language-tsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`0x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Create a key string from a table ID and key tuple to use in our store Map above&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Like `Array.splice`, but for strings of bytes&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;newData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dataNibbles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newDataNibbles&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;newData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;`0x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dataNibbles&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;concat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;newDataNibbles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;number&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/^0x/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;processStoreEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;StoreEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SetRecord&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Overwrite all of the Record&apos;s fields&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SpliceStaticData&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Splice the static field data of the Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;bytesLength&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_SpliceDynamicData&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Splice the dynamic field data of the Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;staticData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;encodedLengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;bytesSplice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;dynamicData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;deleteCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;eventName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Store_DeleteRecord&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;storeKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tableId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;keyTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Delete the whole Record&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;store&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;delete&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;access-control&quot;&gt;Access Control&lt;/h3&gt;

&lt;p&gt;This standard only defines functions to &lt;strong&gt;read&lt;/strong&gt; from the Store (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getFieldLength&lt;/code&gt;). The methods for setting or modifying records in the store are left to each specific implementation. Therefore, implementations &lt;strong&gt;must provide appropriate access control mechanisms&lt;/strong&gt; for writing to the store, tailored to their specific use cases.&lt;/p&gt;

&lt;h3 id=&quot;on-chain-data-accessibility&quot;&gt;On-Chain Data Accessibility&lt;/h3&gt;

&lt;p&gt;All data stored within a store is accessible not only off-chain but also &lt;strong&gt;on-chain&lt;/strong&gt; by other smart contracts through the provided read functions (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getRecord&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getField&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getFieldLength&lt;/code&gt;). This differs from the typical behavior of smart contracts, where internal storage variables are private by default and cannot be directly read by other contracts unless explicit getter functions are provided. Thus, developers must be mindful that any data stored in the store is openly accessible to other smart contracts.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Fri, 08 Nov 2024 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-7813</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-7813</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>Transferable Tokenized Vault Requests</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8161 - Transferable Tokenized Vault Requests&lt;/strong&gt; is in Last Call status. It is authored by Cain O&apos;Sullivan (@cosullivan), Jeroen Offerijns (@hieronx) and was originally created 2025-02-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/draft-erc-transferable-asynchronous-tokenized-vault-requests/27747&quot;&gt;https://ethereum-magicians.org/t/draft-erc-transferable-asynchronous-tokenized-vault-requests/27747&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 extends &lt;a href=&quot;/EIPS/eip-7540&quot;&gt;ERC-7540&lt;/a&gt; by adding optional transferability of pending deposit and redeem Requests. It introduces two separate interfaces that allow a controller to transfer their pending Request balance to a new controller. Implementations may support either or both interfaces independently.&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;/EIPS/eip-7540&quot;&gt;ERC-7540&lt;/a&gt; asynchronous Requests can remain in the Pending state for an extended period of time. During this period, controllers have no way to transfer their position to another address. This creates friction for users who need to migrate wallets, restructure positions across accounts, or integrate with protocols that compose on top of pending Request positions.&lt;/p&gt;

&lt;p&gt;By enabling transferability of pending Requests, this standard unlocks secondary market liquidity for pending positions and simplifies account management without requiring cancelation and re-submission of Requests.&lt;/p&gt;

&lt;p&gt;Transferability is kept optional and split into two separate interfaces so that implementations can choose to support transferable deposit Requests, transferable redeem Requests, both, or neither, depending on their security model and use case.&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;transferable-deposit-requests&quot;&gt;Transferable Deposit Requests&lt;/h3&gt;

&lt;p&gt;Vaults that support transferable deposit Requests MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7540DepositTransferable&lt;/code&gt; interface.&lt;/p&gt;

&lt;h4 id=&quot;transferdepositrequest&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferDepositRequest&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Transfers the entire pending deposit Request balance from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newController&lt;/code&gt; for the given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST only transfer the Pending balance. Claimable balances MUST NOT be affected.&lt;/p&gt;

&lt;p&gt;After a successful transfer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingDepositRequest(requestId, oldController)&lt;/code&gt; MUST decrease by the transferred amount and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingDepositRequest(requestId, newController)&lt;/code&gt; MUST increase by the same amount (less any fees).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt; or an operator approved by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferDepositRequest&lt;/code&gt; event.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;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;transferDepositRequest&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;nonpayable&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;requestId&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;oldController&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;newController&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;transferdepositrequest-1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferDepositRequest&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; has transferred their pending deposit Request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt; for the given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST be emitted when a pending deposit Request is transferred using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferDepositRequest&lt;/code&gt; method.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;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;TransferDepositRequest&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;requestId&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;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;to&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;sender&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;false&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;h3 id=&quot;transferable-redeem-requests&quot;&gt;Transferable Redeem Requests&lt;/h3&gt;

&lt;p&gt;Vaults that support transferable redeem Requests MUST implement the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7540RedeemTransferable&lt;/code&gt; interface.&lt;/p&gt;

&lt;h4 id=&quot;transferredeemrequest&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferRedeemRequest&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;Transfers the entire pending redeem Request balance from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;newController&lt;/code&gt; for the given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST only transfer the Pending balance. Claimable balances MUST NOT be affected.&lt;/p&gt;

&lt;p&gt;After a successful transfer, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingRedeemRequest(requestId, oldController)&lt;/code&gt; MUST decrease by the transferred amount and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pendingRedeemRequest(requestId, newController)&lt;/code&gt; MUST increase by the same amount (less any fees).&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msg.sender&lt;/code&gt; MUST be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt; or an operator approved by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;oldController&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST emit the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferRedeemRequest&lt;/code&gt; event.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;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;transferRedeemRequest&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;nonpayable&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;requestId&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;oldController&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;newController&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;transferredeemrequest-1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TransferRedeemRequest&lt;/code&gt;&lt;/h4&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;from&lt;/code&gt; has transferred their pending redeem Request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to&lt;/code&gt; for the given &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestId&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;MUST be emitted when a pending redeem Request is transferred using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferRedeemRequest&lt;/code&gt; method.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;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;TransferRedeemRequest&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;requestId&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;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;to&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;sender&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;false&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;h3 id=&quot;erc-165-support&quot;&gt;&lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; Support&lt;/h3&gt;

&lt;p&gt;Smart contracts implementing this standard MUST implement the &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Vaults implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7540DepositTransferable&lt;/code&gt; MUST return the constant value &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;0x53b3bb0a&lt;/code&gt; is passed through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interfaceID&lt;/code&gt; argument.&lt;/p&gt;

&lt;p&gt;Vaults implementing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IERC7540RedeemTransferable&lt;/code&gt; MUST return the constant value &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;0x7846f5bd&lt;/code&gt; is passed through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;interfaceID&lt;/code&gt; argument.&lt;/p&gt;

&lt;h2 id=&quot;rationale&quot;&gt;Rationale&lt;/h2&gt;

&lt;h3 id=&quot;only-transferring-pending-balances&quot;&gt;Only Transferring Pending Balances&lt;/h3&gt;

&lt;p&gt;This standard deliberately restricts transfers to the Pending state. Claimable balances already have a deterministic exchange rate and can be claimed by the controller at any time; transferring them would add complexity without significant benefit. Limiting scope to Pending balances keeps the interface simple and avoids edge cases around partial claimability.&lt;/p&gt;

&lt;h3 id=&quot;separate-interfaces-for-deposit-and-redeem-transferability&quot;&gt;Separate Interfaces for Deposit and Redeem Transferability&lt;/h3&gt;

&lt;p&gt;Following the design philosophy of &lt;a href=&quot;/EIPS/eip-7540&quot;&gt;ERC-7540&lt;/a&gt; where deposit and redemption flows are independently optional, this standard keeps deposit and redeem transferability as separate interfaces. A Vault may have valid reasons to allow transferability of one request type but not the other. For example, a Vault might allow transfer of pending deposit Requests (where assets are locked) but disallow transfer of pending redeem Requests (where shares have already been burned or locked with specific accounting implications).&lt;/p&gt;

&lt;h3 id=&quot;transferring-the-full-pending-balance&quot;&gt;Transferring the Full Pending Balance&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferDepositRequest&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transferRedeemRequest&lt;/code&gt; methods transfer the entire pending balance rather than accepting a partial amount. This simplifies the interface and aligns with the ERC-7540 model where Requests of the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requestId&lt;/code&gt; are fungible.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;This standard is fully backward compatible with &lt;a href=&quot;/EIPS/eip-7540&quot;&gt;ERC-7540&lt;/a&gt;. Vaults that do not implement this extension continue to function as before. Integrators can detect support for transferability via &lt;a href=&quot;/EIPS/eip-165&quot;&gt;ERC-165&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;supportsInterface&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;h3 id=&quot;operator-trust&quot;&gt;Operator Trust&lt;/h3&gt;

&lt;p&gt;As with ERC-7540, operators approved by a controller can transfer pending Requests on their behalf. Users must be aware that granting operator permissions extends to the ability to transfer pending Requests to arbitrary addresses, effectively moving locked assets or shares out of the controller’s control.&lt;/p&gt;

&lt;h3 id=&quot;pricing-of-pending-requests&quot;&gt;Pricing of Pending Requests&lt;/h3&gt;

&lt;p&gt;Unlike Vault shares, which have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;convertToShares&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;convertToAssets&lt;/code&gt; as onchain price references, pending Requests have no built-in pricing mechanism. The exchange rate is unknown until fulfillment. Builders of secondary markets around transferable Requests should account for this lack of a canonical price source when designing pricing and settlement mechanisms.&lt;/p&gt;

&lt;h2 id=&quot;copyright&quot;&gt;Copyright&lt;/h2&gt;

&lt;p&gt;Copyright and related rights waived via &lt;a href=&quot;/LICENSE&quot;&gt;CC0&lt;/a&gt;.&lt;/p&gt;

      </description>
        <pubDate>Wed, 12 Feb 2025 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8161</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8161</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
      
      <item>
        <title>AI Agent Authenticated Wallet</title>
        <description>
        &lt;p&gt;&lt;strong&gt;EIP #8196 - AI Agent Authenticated Wallet&lt;/strong&gt; is in Last Call status. It is authored by Leigh Cronian (@cybercentry) &lt;leigh.cronian@cybercentry.co.uk&gt;, Chris Johnson &lt;chris@virtuals.io&gt; and was originally created 2026-03-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/erc-8196-ai-agent-authenticated-wallet/27987&quot;&gt;https://ethereum-magicians.org/t/erc-8196-ai-agent-authenticated-wallet/27987&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 a standard interface for AI agent-authenticated wallets. These wallets execute transactions only when accompanied by verifiable cryptographic proof that the action complies with a specific policy defined by the asset owner.&lt;/p&gt;

&lt;p&gt;It serves as &lt;strong&gt;Layer 3 (Execute)&lt;/strong&gt; in a modular trust stack designed for secure autonomous AI agents:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Layer 1 (Register)&lt;/strong&gt;: &lt;a href=&quot;/EIPS/eip-8004&quot;&gt;ERC-8004&lt;/a&gt; - on-chain identity and registration&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Layer 2 (Verify)&lt;/strong&gt;: &lt;a href=&quot;/EIPS/eip-8126&quot;&gt;ERC-8126&lt;/a&gt; - verification/risk scoring&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Layer 3 (Execute)&lt;/strong&gt;: This standard - policy-bound execution with immutable audit trail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design enables secure credential delegation without exposing private keys, prevents host manipulation of agent behavior, provides tamper-evident logging of all session activity, and ensures users retain final say over their agents and actions, as emphasized in the EF Mandate (“a user has the final say over their identities, assets, actions, and agents”).&lt;/p&gt;

&lt;h2 id=&quot;motivation&quot;&gt;Motivation&lt;/h2&gt;

&lt;p&gt;Autonomous AI agents introduce critical security challenges when performing on-chain actions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Hosting Trust Trap&lt;/strong&gt; - Hosts can steal private keys if agents hold funds directly&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Blind Delegation&lt;/strong&gt; - Credential delegation to agents lacks enforceable limits or auditable compliance&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Host Manipulation&lt;/strong&gt; - Malicious hosts can suppress outputs, delay requests, replay probabilistic queries, or influence agent behavior through repeated sampling&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Malicious Historical Activity&lt;/strong&gt; - Agents with prior sanctions, mixer usage, bot-like patterns, rapid forwarding, or clustering with tainted addresses pose ongoing risk&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Replay &amp;amp; Timing Vulnerabilities&lt;/strong&gt; - Valid proofs from the past can be reused, or timing manipulated to the host’s advantage&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This ERC provides the execution layer in a composable trust stack to mitigate these risks:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Layer&lt;/th&gt;
      &lt;th&gt;Purpose&lt;/th&gt;
      &lt;th&gt;Standard&lt;/th&gt;
      &lt;th&gt;Core Question&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;Register&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-8004&quot;&gt;ERC-8004&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;“Does this agent exist on-chain?”&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;Verify&lt;/td&gt;
      &lt;td&gt;&lt;a href=&quot;/EIPS/eip-8126&quot;&gt;ERC-8126&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;“Is this agent trustworthy and free of malicious signals?”&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Execute&lt;/td&gt;
      &lt;td&gt;This ERC&lt;/td&gt;
      &lt;td&gt;“Is this action authorized right now?”&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Key features include:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Cryptographically enforced policy compliance&lt;/li&gt;
  &lt;li&gt;Immutable, hash-chained audit trail for verifiable delegation&lt;/li&gt;
  &lt;li&gt;Entropy commit-reveal to counter host influence on probabilistic agents&lt;/li&gt;
  &lt;li&gt;Active containment mechanisms (recommended) for real-time violation response&lt;/li&gt;
  &lt;li&gt;Legacy credential delegation via TLS attestations&lt;/li&gt;
  &lt;li&gt;User sovereignty over agent actions via enforceable, auditable policy compliance, emphasising final user control over agents and actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The verification layer allows flexibility while strongly encouraging checks (e.g. via ERC-8126 Wallet Verification) against historical malicious behavior before granting control.&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 and RFC 8174.&lt;/p&gt;

&lt;h3 id=&quot;trust-stack-integration&quot;&gt;Trust Stack Integration&lt;/h3&gt;

&lt;p&gt;This ERC defines an on-chain smart contract interface (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAIAgentAuthenticatedWallet&lt;/code&gt;). Implementations are expected to be smart contracts (such as &lt;a href=&quot;/EIPS/eip-4337&quot;&gt;ERC-4337&lt;/a&gt; account abstraction wallets or dedicated policy enforcement modules) that implement this interface.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Verification Check (ERC-8126): Implementations MUST perform a verification check using ERC-8126 before executing any agent action. The policy’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minVerificationScore&lt;/code&gt; field MUST be enforced. Actions MUST be rejected if the agent’s current ERC-8126 score exceeds the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minVerificationScore&lt;/code&gt; value set in the policy. The agent’s ERC-8126 score MUST be looked up by the policy’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;agentId&lt;/code&gt; via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getLatestRiskScore&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Off-chain components (such as agent hosting services, wallet UIs, and relayers) SHOULD also perform the same verification checks before submitting transactions or UserOperations.&lt;/p&gt;

&lt;h3 id=&quot;agent-policy-structure&quot;&gt;Agent Policy Structure&lt;/h3&gt;

&lt;p&gt;Policies MUST include the following fields:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Field&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Required&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;policyId&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes32&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Unique policy identifier&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;agentAddress&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Authorized AI agent address&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;agentId&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;ERC-8004 agent id; key for the ERC-8126 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getLatestRiskScore&lt;/code&gt; lookup&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ownerAddress&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Asset owner / delegator&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowedActions&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;List of permitted actions (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&quot;transfer&quot;, &quot;swap&quot;]&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;allowedContracts&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Whitelist of target contracts&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blockedContracts&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;address[]&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Blacklist of contracts&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuePerTx&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Maximum value per transaction (in wei)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxValuePerDay&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;No&lt;/td&gt;
      &lt;td&gt;Optional daily spending limit (in wei)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validAfter&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Timestamp when the policy becomes active&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;validUntil&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint256&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Timestamp when the policy expires&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minVerificationScore&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;uint8&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Yes&lt;/td&gt;
      &lt;td&gt;Minimum ERC-8126 verification score required (20 = Low Risk tier; scores 0–20 allowed; lower score = lower risk)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;erc-712-types&quot;&gt;&lt;a href=&quot;/EIPS/eip-712&quot;&gt;ERC-712&lt;/a&gt; Types&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;bytes32 constant AGENT_ACTION_TYPEHASH = keccak256(
    &quot;AgentAction(address agent,string action,address target,uint256 value,bytes data,uint256 nonce,uint256 validUntil,bytes32 policyHash,bytes32 entropyCommitment)&quot;
);

bytes32 constant DELEGATION_TYPEHASH = keccak256(
    &quot;Delegation(address delegator,address delegatee,bytes32 policyHash,uint256 validUntil,uint256 nonce)&quot;
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;core-interface&quot;&gt;Core Interface&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.20;

interface IAIAgentAuthenticatedWallet {
    event PolicyRegistered(
        bytes32 indexed policyHash,
        address indexed owner,
        address indexed agent,
        uint256 validUntil
    );

    event ActionExecuted(
        bytes32 indexed policyHash,
        address indexed agent,
        address target,
        uint256 value,
        bytes32 auditEntryId
    );

    event PolicyRevoked(
        bytes32 indexed policyHash,
        string reason
    );

    event AuditEntryLogged(
        bytes32 indexed entryId,
        uint256 sequence,
        bytes32 sessionId,
        string actionType
    );

    function registerPolicy(
        address agent,
        uint256 agentId,
        string[] calldata allowedActions,
        address[] calldata allowedContracts,
        address[] calldata blockedContracts,
        uint256 maxValuePerTx,
        uint256 maxValuePerDay,
        uint256 validAfter,
        uint256 validUntil,
        uint8 minVerificationScore
    ) external returns (bytes32 policyHash);

    function executeAction(
        bytes32 policyHash,
        address target,
        uint256 value,
        bytes calldata data,
        uint256 nonce,
        bytes32 entropyCommitment,
        bytes calldata signature
    ) external returns (bool success, bytes32 auditEntryId);

    function revokePolicy(bytes32 policyHash, string calldata reason) external;

    function getPolicy(bytes32 policyHash) external view returns (
        address agent,
        address owner,
        uint256 maxValuePerTx,
        uint256 validUntil,
        bool isActive
    );
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;audit-trail-hash-chained&quot;&gt;Audit Trail (Hash-Chained)&lt;/h3&gt;

&lt;p&gt;Each audit entry MUST include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;previousHash&lt;/code&gt; for integrity. Implementations MAY store entries off-chain (e.g. IPFS) with periodic Merkle roots anchored on-chain (for example, to ERC-8004’s Validation Registry).&lt;/p&gt;

&lt;h3 id=&quot;error-codes&quot;&gt;Error Codes&lt;/h3&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;error PolicyExpired(bytes32 policyHash, uint256 validUntil);
error ValueExceedsLimit(uint256 value, uint256 maxValue);
error InvalidSignature(address recovered, address expected);
error EntropyVerificationFailed(bytes32 commitment, bytes32 revealed);
error PolicyViolation(bytes32 policyHash, string reason);
&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;Separation of concerns: identity (ERC-8004) and verification (ERC-8126) decoupled from execution, with verification enforced via policy&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;policyHash&lt;/code&gt; in ERC-712 signatures binds actions immutably&lt;/li&gt;
  &lt;li&gt;Hash-chain audit provides tamper detection without full on-chain cost&lt;/li&gt;
  &lt;li&gt;Verification gating allows flexibility while encouraging trust standards like ERC-8126&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This specification explores novel combinations of policy-bound signing, hash-chained auditing, and entropy commitments to enable verifiable agent autonomy under potentially hostile hosts, with open questions regarding gas-efficient audit roots, threshold-based containment mechanisms, and the enforcement of Censorship Resistant, Open Source, Private, and Secure (CROPS) properties in high-value agent scenarios.&lt;/p&gt;

&lt;h2 id=&quot;backwards-compatibility&quot;&gt;Backwards Compatibility&lt;/h2&gt;

&lt;p&gt;Compatible with ERC-4337 wallets and existing standards. No breaking changes.&lt;/p&gt;

&lt;h2 id=&quot;security-considerations&quot;&gt;Security Considerations&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Expiration checks and nonce uniqueness should be enforced to prevent replay attacks.&lt;/li&gt;
  &lt;li&gt;The hash-chained audit trail makes tampering detectable through broken hash links.&lt;/li&gt;
  &lt;li&gt;Host manipulation remains a probabilistic risk. For high-value agents, using multiple independent hosts is recommended to reduce this threat.&lt;/li&gt;
  &lt;li&gt;A recent verification via ERC-8126 with a low risk score is required before delegation. Special attention must be given to clean Wallet Verification (WV) results showing no signs of sanctions, mixer usage, bot-like patterns, rapid forwarding, or threat intelligence hits.&lt;/li&gt;
  &lt;li&gt;Wallets must reject or revoke delegations if the ERC-8126 Wallet Verification flags malicious activity (such as sanctioned funding, clustering with known bad actors, or strong automation indicators), even if the overall risk score appears acceptable.&lt;/li&gt;
  &lt;li&gt;User sovereignty must remain the highest priority. Designs should ensure users retain final control over their agents and actions, and avoid any mechanism that introduces blind trust or unaccountable intermediation.&lt;/li&gt;
  &lt;li&gt;The system should be designed with CROPS principles in mind: strong censorship resistance, verifiable security, and privacy preservation (minimizing on-chain data exposure through ERC-8126 gating).&lt;/li&gt;
  &lt;li&gt;Active containment mechanisms should be implemented where possible. These allow users to respond quickly to policy violations and help preserve sovereignty.&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>Sat, 14 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://eips.ethereum.org//EIPS/eip-8196</link>
        <guid isPermaLink="true">https://eips.ethereum.org//EIPS/eip-8196</guid>
      </item>
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
      
    
  </channel>
</rss>
