{"action":"created","issue":{"url":"https://api.github.com/repos/ethereum/EIPs/issues/1411","repository_url":"https://api.github.com/repos/ethereum/EIPs","labels_url":"https://api.github.com/repos/ethereum/EIPs/issues/1411/labels{/name}","comments_url":"https://api.github.com/repos/ethereum/EIPs/issues/1411/comments","events_url":"https://api.github.com/repos/ethereum/EIPs/issues/1411/events","html_url":"https://github.com/ethereum/EIPs/issues/1411","id":360071634,"node_id":"MDU6SXNzdWUzNjAwNzE2MzQ=","number":1411,"title":"ERC 1400: Security Token Standard","user":{"login":"adamdossa","id":2633913,"node_id":"MDQ6VXNlcjI2MzM5MTM=","avatar_url":"https://avatars1.githubusercontent.com/u/2633913?v=4","gravatar_id":"","url":"https://api.github.com/users/adamdossa","html_url":"https://github.com/adamdossa","followers_url":"https://api.github.com/users/adamdossa/followers","following_url":"https://api.github.com/users/adamdossa/following{/other_user}","gists_url":"https://api.github.com/users/adamdossa/gists{/gist_id}","starred_url":"https://api.github.com/users/adamdossa/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adamdossa/subscriptions","organizations_url":"https://api.github.com/users/adamdossa/orgs","repos_url":"https://api.github.com/users/adamdossa/repos","events_url":"https://api.github.com/users/adamdossa/events{/privacy}","received_events_url":"https://api.github.com/users/adamdossa/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":82,"created_at":"2018-09-13T21:22:51Z","updated_at":"2018-10-01T22:58:13Z","closed_at":null,"author_association":"NONE","body":"---\r\n\r\neip: ERC1400\r\ntitle: Security Token Standard\r\nauthor: Adam Dossa (@adamdossa), Pablo Ruiz (@pabloruiz55), Fabian Vogelsteller (@frozeman), Stephane Gosselin (@thegostep)\r\ndiscussions-to: #1411\r\nstatus: Draft\r\ntype: Standards Track\r\ncategory: ERC\r\ncreated: 2018-09-09\r\nrequire: ERC-1066 (#1066), ERC-1410 (#1410)\r\n\r\n---\r\n\r\n## Simple Summary\r\n\r\nA standard interface for issuing security tokens, managing their ownership and transfer restrictions.\r\n\r\n## Abstract\r\n\r\nBuilds on the partially fungible token standard (ERC 1410 (#1410)) to provide additional functionality to manage different types of ownership of fungible tokens representing asset ownership.\r\n\r\nThis standard can be optionally extended to implement ERC777 and ERC20 (see Backwards Compatibility in ERC 1410 #1410).\r\n\r\n## Motivation\r\n\r\nAccelerate the issuance and management of securities on the Ethereum blockchain by specifying a standard interface through which security tokens can be operated on and interrogated by all relevant parties.\r\n\r\nSecurity tokens differ materially from other token use-cases, with more complex interactions between off-chain and on-chain actors, and considerable regulatory scrutiny.\r\n\r\nSecurity tokens should be able to represent any asset class, be issued and managed across any jurisdiction, and comply with the associated regulatory restrictions.\r\n\r\n## Requirements\r\n\r\nMoving the issuance, trading and lifecycle events of a security onto a public ledger requires having a standard way of modeling securities, their ownership and their properties on-chain.\r\n\r\nThe following requirements have been compiled following discussions with parties across the Security Token ecosystem.\r\n\r\n- MUST have a standard interface to query if a transfer would be successful and return a reason for failure.\r\n- MUST be able to perform forced transfer for legal action or fund recovery.\r\n- MUST emit standard events for issuance and redemption.\r\n- MUST be able to attach metadata to a subset of a token holder's balance such as special shareholder rights or data for transfer restrictions.\r\n- MUST be able to modify metadata at time of transfer based on off-chain data, on-chain data and the parameters of the transfer.\r\n- MAY require signed data to be passed into a transfer transaction in order to validate it on-chain.\r\n- SHOULD NOT restrict the range of asset classes across jurisdictions which can be represented.\r\n- SHOULD be ERC20 and ERC777 compatible.\r\n\r\n## Abstract\r\n\r\nThere are many types of securities which, although they represent the same underlying asset, need to have differentiating data tied to them.\r\n\r\nThis additional metadata implicitly renders these securities non-fungible, but in practice this data is usually applied to a subset of the security rather than an individual security. The ability to partition a token holder's balance into tranches, each with separate metadata is addressed in the Partially-Fungible Token section.\r\n\r\nFor example a token holder's balance may be split in two: Those tokens issued during the primary issuance, and those received through secondary trading.\r\n\r\nSecurity token contracts can reference this metadata in order to apply additional logic to determine whether or not a transfer is valid, and determine the metadata that should be associated with the tokens once transferred into the receiver's balance.\r\n\r\nTo represent securities metadata we use the ERC 1410 (#1410) - Partially Fungible Token Standard.\r\n\r\nTransfers of securities can fail for a variety of reasons in contrast to utility tokens which generally only require the sender to have a sufficient balance.\r\n\r\nThese conditions could be related to metadata of the securities being transferred (i.e. whether they are subject to a lock-up period), the identity of the sender and receiver of the securities (i.e. whether they have been through a KYC process, whether they are accredited or an affiliate of the issuer) or for reasons unrelated to the specific transfer but instead set at the token level (i.e. the token contract enforces a maximum number of investors or a cap on the percentage held by any single investor).\r\n\r\nFor ERC20 / ERC777 tokens, the `balanceOf` and `allowance` functions provide a way to check that a transfer is likely to succeed before executing the transfer, which can be executed both on and off-chain.\r\n\r\nFor tokens representing securities the standard introduces a function `canSend` which provides a more general purpose way to achieve this when the reasons for failure are more complex; and a function of the whole transfer (i.e. includes any data sent with the transfer and the receiver of the securities).\r\n\r\nIn order to provide a richer result than just true or false, a byte return code is returned. This allows us to give a reason for why the transfer failed, or at least which category of reason the failure was in. The ability to query documents and the expected success of a transfer is included in Security Token section.\r\n\r\n## Specification\r\n\r\n### Document Management\r\n\r\n#### getDocument / setDocument\r\n\r\nThese functions are used to manage a library of documents associated with the token. These documents can be legal documents, or other reference materials.\r\n\r\nA document is associated with a short name (represented as a `bytes32`) and can optionally have a hash of the document contents associated with it on-chain.\r\n\r\n``` solidity\r\nfunction getDocument(bytes32 _name) external view returns (string, bytes32);\r\nfunction setDocument(bytes32 _name, string _uri, bytes32 _documentHash) external;\r\n```\r\n\r\n### Transfer Validity\r\n\r\n#### canSend\r\n\r\nTransfers of securities may fail for a number of reasons, for example relating to:\r\n  - the identity of the sender or receiver of the tokens\r\n  - limits placed on the specific tokens being transferred (i.e. limits associated with the tranche of the tokens being tranferred)\r\n  - limits related to the overall state of the token (i.e. total number of investors)\r\n\r\nThe standard provides an on-chain function to determine whether a transfer will succeed, and return details indicating the reason if the transfer is not valid.\r\n\r\nThese rules can either be defined using smart contracts and on-chain data, or rely on `_data` passed as part of the `sendByTranche` function which could represent authorisation for the transfer (e.g. a signed message by a transfer agent attesting to the validity of this specific transfer).\r\n\r\nThe function will return both a ESC (Ethereum Status Code) following the EIP-1066 standard, and an additional `bytes32` parameter that can be used to define application specific reason codes with additional details (for example the transfer restriction rule responsible for making the send operation invalid).\r\n\r\nIt also returns the destination tranche of the tokens being transferred in an analogous way to `sendByTranche`.\r\n\r\n``` solidity\r\nfunction canSend(address _from, address _to, bytes32 _tranche, uint256 _amount, bytes _data) external view returns (byte, bytes32, bytes32);\r\n```\r\n\r\n### Token Issuance\r\n\r\n#### isIssuable\r\n\r\nA security token issuer can specify that issuance has finished for the token (i.e. no new tokens can be minted or issued).\r\n\r\nIf a token returns FALSE for `isIssuable()` then it MUST always return FALSE in the future.\r\n\r\n``` solidity\r\nfunction isIssuable() external view returns (bool);\r\n```\r\n\r\n#### issueByTranche\r\n\r\nThis function must be called to increase the total supply.\r\n\r\nWhen called, this function MUST emit the `IssuedByTranche` event.\r\n\r\n``` solidity\r\nfunction issueByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _data) external;\r\n```\r\n\r\n### Token Redemption\r\n\r\n#### operatorRedeemByTranche\r\n\r\nAllows an operator to burn or redeem tokens on behalf of a token holder.\r\n\r\nThe burnt or redeemed tokens must be subtracted from the total supply and the balance of the token holder. The token burn should act like sending tokens and be subject to the same conditions. The `BurnedByTranche` event must be emitted every time this function is called.\r\n\r\n``` solidity\r\nfunction operatorRedeemByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _operatorData) external;\r\n```\r\n\r\n#### redeemByTranche\r\n\r\nAllows a token holder to burn or redeem tokens.\r\n\r\nThe burnt or redeemed tokens must be subtracted from the total supply and the balance of the token holder. The token burn should act like sending tokens and be subject to the same conditions. The `BurnedByTranche` event must be emitted every time this function is called.\r\n\r\n``` solidity\r\nfunction redeemByTranche(bytes32 _tranche, uint256 _amount, bytes _data) external;\r\n```\r\n\r\n### Controller Operation\r\n\r\nIn order to provide transparency over whether `defaultOperators` or `defaultOperatorsByTranche` can be defined by the issuer, the function `isControllable` can be used.\r\n\r\nIf a token returns FALSE for `isControllable()` then it MUST:\r\n  - always return FALSE in the future.\r\n  - return empty lists for `defaultOperators` and `defaultOperatorsByTranche`\r\n  - never add addresses for `defaultOperators` and `defaultOperatorsByTranche`\r\n\r\nIn other words, if an issuer sets `isControllable` to return TRUE, then there can be no default operators for the token.\r\n\r\n``` solidity\r\nfunction isControllable() external view returns (bool);\r\n```\r\n\r\n### Interface\r\n\r\n``` solidity\r\n/// @title IERCST Security Token Standard (EIP 1400)\r\n/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec\r\n\r\ninterface IERCST is IERCPFT {\r\n\r\n    // Document Management\r\n    function getDocument(bytes32 _name) external view returns (string, bytes32);\r\n    function setDocument(bytes32 _name, string _uri, bytes32 _documentHash) external;\r\n\r\n    // Controller Operation\r\n    function isControllable() external view returns (bool);\r\n\r\n    // Token Issuance\r\n    function isIssuable() external view returns (bool);\r\n    function issueByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _data) external;\r\n    event IssuedByTranche(bytes32 indexed tranche, address indexed operator, address indexed to, uint256 amount, bytes data, bytes operatorData);\r\n\r\n    // Token Redemption\r\n    function redeemByTranche(bytes32 _tranche, uint256 _amount, bytes _data) external;\r\n    function operatorRedeemByTranche(bytes32 _tranche, address _tokenHolder, uint256 _amount, bytes _operatorData) external;\r\n    event RedeemedByTranche(bytes32 indexed tranche, address indexed operator, address indexed from, uint256 amount, bytes operatorData);\r\n\r\n    // Transfer Validity\r\n    function canSend(address _from, address _to, bytes32 _tranche, uint256 _amount, bytes _data) external view returns (byte, bytes32, bytes32);\r\n\r\n}\r\n```\r\n\r\n### Notes\r\n\r\n#### Forced Transfers\r\n\r\nIt may be that regulations require an issuer or a trusted third party to retain the power to transfer tokens on behalf of investors. As such, the ERC-1400 (Security Token Standard) specification supersedes ERC-1410 (Partially Fungible Tokens) in that a token holder MUST NOT be allowed revoke a default operator or tranche default operator.\r\n\r\n#### Restricted Transfers\r\n\r\nTransfers of security tokens can fail for a number of reasons in contrast to utility tokens which generally only require the sender to have a sufficient balance.\r\n\r\nThese conditions could be related to metadata of the security tokens being transferred (i.e. whether they are subject to a lock-up period), the identity and eligibility of the sender and receiver of the tokens (i.e. whether they have been through a KYC process and whether they are accredited or an affiliate of the issuer) or for reasons unrelated to the specific transfer but instead set at the security level for regulatory purposes (i.e. the security enforces a maximum number of investors or a cap on the percentage held by any single investor).\r\n\r\nFor utility tokens (ERC20 / ERC777) the `balanceOf` and `allowance` functions provide a way to check that a transfer is likely to succeed before executing the transfer which, can be executed both on and off-chain.\r\n\r\nThe standard introduces a function `canSend` which provides a more general purpose way to query if sending tokens would be successful. It accepts a set of parameters which may include signed data and returns a reason byte code with information about the success or failure of the transaction.\r\n\r\nNB - the result of a call to `canSend` may change depending on on-chain state (including block numbers or timestamps) and possibly off-chain oracles. As such, it does not provide guarantees that a future transfer will be successful after being called as a view function that does not modify any state.\r\n\r\n#### Identity\r\n\r\nUnder many jurisdictions, whether a party is able to receive and send security tokens depends on the characteristics of the party's identity. For example, most jurisdictions require some level of KYC / AML process before a party is eligible to purchase or sell a particular security. Additionally, a party may be categorized into an investor qualification category (e.g. accredited investor, qualified purchaser), and their citizenship may also inform restrictions associated with their securities.\r\n\r\nThere are various identity standards (e.g. ERC725, Civic, uPort) which can be used to capture the party's identity data, as well as other approaches which are centrally managed (e.g. maintaining a whitelist of addresses that have been approved from a KYC perspective). These identity standards have in common to key off an Ethereum address (which could be a party's wallet, or an identity contract), and as such the `canSend` function can use the address of both the sender and receiver of the security token as a proxy for identity in deciding if eligibility requirements are met.\r\n\r\nBeyond this, the standard does not mandate any particular approach to identity.\r\n\r\n#### Reason Codes\r\n\r\nTo improve the token holder experience, `canSend` MUST return a reason byte code on success or failure based on the EIP-1066 application-specific status codes specified below. An implementation can also return arbitrary data as a `bytes32` to provide additional information not captured by the reason code.\r\n\r\n| Code   | Reason                                                        |\r\n| ------ | ------------------------------------------------------------- |\r\n| `0xA0` | Transfer Verified - Unrestricted                              |\r\n| `0xA1` | Transfer Verified - On-Chain approval for restricted token    |\r\n| `0xA2` | Transfer Verified - Off-Chain approval for restricted token   |\r\n| `0xA3` | Transfer Blocked - Sender lockup period not ended             |\r\n| `0xA4` | Transfer Blocked - Sender balance insufficient                |\r\n| `0xA5` | Transfer Blocked - Sender not eligible                        |\r\n| `0xA6` | Transfer Blocked - Receiver not eligible                      |\r\n| `0xA7` | Transfer Blocked - Identity restriction                       |\r\n| `0xA8` | Transfer Blocked - Token restriction                          |\r\n| `0xA9` | Transfer Blocked - Token granularity                          |\r\n| `0xAA` |                                                               |\r\n| `0xAB` |                                                               |\r\n| `0xAC` |                                                               |\r\n| `0xAD` |                                                               |\r\n| `0xAE` |                                                               |\r\n| `0xAF` |                                                               |\r\n\r\n#### On-chain vs. Off-chain Transfer Restrictions\r\n\r\nThe rules determining if a security token can be sent may be self-executing (e.g. a rule which limits the maximum number of investors in the security) or require off-chain inputs (e.g. an explicit broker approval for the trade). To facilitate the latter, the `sendByTranche` and `canSend` functions accept an additional `bytes _data` parameter which can be signed by an approved party and used to validate a transfer.\r\n\r\nThe specification for this data is outside the scope of this standard and would be implementation specific.\r\n\r\n## References\r\n- [EIP 1410: Partially Fungible Token Standard](https://github.com/ethereum/EIPs/issues/1410)\r\n- [EIP Draft](https://github.com/SecurityTokenStandard/EIP-Spec)\r\n\r\n_Copied from original issue_: https://github.com/ethereum/EIPs/issues/1400"},"comment":{"url":"https://api.github.com/repos/ethereum/EIPs/issues/comments/426091602","html_url":"https://github.com/ethereum/EIPs/issues/1411#issuecomment-426091602","issue_url":"https://api.github.com/repos/ethereum/EIPs/issues/1411","id":426091602,"node_id":"MDEyOklzc3VlQ29tbWVudDQyNjA5MTYwMg==","user":{"login":"jllaw","id":5771238,"node_id":"MDQ6VXNlcjU3NzEyMzg=","avatar_url":"https://avatars1.githubusercontent.com/u/5771238?v=4","gravatar_id":"","url":"https://api.github.com/users/jllaw","html_url":"https://github.com/jllaw","followers_url":"https://api.github.com/users/jllaw/followers","following_url":"https://api.github.com/users/jllaw/following{/other_user}","gists_url":"https://api.github.com/users/jllaw/gists{/gist_id}","starred_url":"https://api.github.com/users/jllaw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jllaw/subscriptions","organizations_url":"https://api.github.com/users/jllaw/orgs","repos_url":"https://api.github.com/users/jllaw/repos","events_url":"https://api.github.com/users/jllaw/events{/privacy}","received_events_url":"https://api.github.com/users/jllaw/received_events","type":"User","site_admin":false},"created_at":"2018-10-01T22:58:13Z","updated_at":"2018-10-01T22:58:13Z","author_association":"NONE","body":"Ok....So for those in NYC, here are our options: \r\n1) Oct 3 - discuss at the security token meetup (and they can carve out a period for panel probably) OR\r\n2) Oct 4 - discuss aboard a harbor cruise (tickets will be comped)\r\n\r\nWhat's the preference?  Note that you can't be late to the harbor cruise and once you are on, you are stuck there for a while. "}}
{"actor":{"display_login":"jllaw"}}