Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ERC 1400: Security Token Standard #1411

Closed
adamdossa opened this issue Sep 13, 2018 · 126 comments
Closed

ERC 1400: Security Token Standard #1411

adamdossa opened this issue Sep 13, 2018 · 126 comments
Labels

Comments

@adamdossa
Copy link

adamdossa commented Sep 13, 2018


eip: ERC-1400
title: Security Token Standards
author: Adam Dossa (@adamdossa), Pablo Ruiz (@pabloruiz55), Fabian Vogelsteller (@frozeman), Stephane Gosselin (@thegostep)
discussions-to: #1411
status: Draft
type: Standards Track
category: ERC
created: 2018-09-09
require: ERC-1410 (#1410), ERC-1594 (#1594), ERC-1644 (#1644), ERC-1643 (#1643), ERC-20 (#20), ERC-1066 (#1066)


Simple Summary

Represents a library of standards for security tokens on Ethereum.

In aggregate provides a suite of standard interfaces for issuing / redeeming security tokens, managing their ownership and transfer restrictions and providing transparency to token holders on how different subsets of their token balance behave with respect to transfer restrictions, rights and obligations.

Abstract

Standards should be backwards compatible with ERC-20 (#20) and easily extended to be compatible with ERC-777 (#777).

ERC-1410 (#1410): differentiated ownership / transparent restrictions
ERC-1594 (#1594): on-chain restriction checking with error signalling, off-chain data injection for transfer restrictions and issuance / redemption semantics
ERC-1643 (#1643): document / legend management
ERC-1644 (#1644): controller operations (force transfer)

Motivation

Accelerate the issuance and management of securities on the Ethereum blockchain by specifying standard interfaces through which security tokens can be operated on and interrogated by all relevant parties.

Taken together, these security token standards provide document management, error signalling, gate keeper (operator) access control, off-chain data injection, issuance / redemption semantics and expose partially fungible subsets of a token holders balance.

Requirements

Moving the issuance, trading and lifecycle events of a security onto a public ledger requires having a standard way of modelling securities, their ownership and their properties on-chain.

The following requirements have been compiled following discussions with parties across the Security Token ecosystem.

  • MUST have a standard interface to query if a transfer would be successful and return a reason for failure.
  • MUST be able to perform forced transfer for legal action or fund recovery.
  • MUST emit standard events for issuance and redemption.
  • 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.
  • MUST be able to modify metadata at time of transfer based on off-chain data, on-chain data and the parameters of the transfer.
  • MUST support querying and subscribing to updates on any relevant documentation for the security.
  • MAY require signed data to be passed into a transfer transaction in order to validate it on-chain.
  • SHOULD NOT restrict the range of asset classes across jurisdictions which can be represented.
  • MUST be ERC-20 compatible.
  • COULD be ERC-777 compatible.

Rationale

ERC-1594: Core Security Token Standard

Transfers 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.

These 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).

For ERC-20 tokens, the balanceOf and allowance functions provide a way to check that a transfer is likely to succeed before executing the transfer, which can be executed both on and off-chain.

For tokens representing securities the standard introduces a function canTransfer / canTransferByPartition 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).

In 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.

In order to support off-chain data inputs to transfer functions, transfer functions are extended to transferWithData / transferFromWithData which can optionally take an additional bytes _data parameter.

ERC-1410: Partially Fungible Tokens

There are many types of securities which, although they represent the same underlying asset, need to have differentiating data tied to them.

This 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 partitions, each with separate metadata is addressed in the Partially Fungible Token section.

For example a token holder's balance may be split in two: those tokens issued during the primary issuance, and those received through secondary trading.

Security 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.

Alternatively a security token can use this mechanism simply to be able to transparently display to investors how different subsets of their tokens will behave with respect to transfer restrictions. In this case, the balances could be determined programatically.

ERC-1643: Document Management Standard

Security tokens usually have documentation associated with them. This could be an offering document, legend details and so on.

Being able to set / remove and retrieve these documents, and having events associated with these actions allows investors to stay up to date with documentation on their investments.

This standard does not provide any way for an investor to signal on-chain that they have read, or agree, with any of these documents.

ERC-1644: Controller Token Operation Standard

Since security tokens are subject to regulatory and legal oversight (the details of which will vary depending on jurisdiction, regulatory framework and underlying asset) in many instances the issuer (or a party delegated to by the issuer acting as a controller, e.g. a regulator or transfer agent) will need to retain the ability to force transfer tokens between addresses.

These controller transfers should be transparent (emit events that flag this as a forced transfer) and the token contract itself should be explicit as to whether or not this is possible.

Examples of where this may be needed is to reverse fraudulent transactions, resolve lost private keys and responding to a court order.

Specification

This standard does not specify any additional functions, but references ERC-1410 (#1410), ERC-1594 (#1594), ERC-1643 (#1643) and ERC-1655 (#1644) as an underlying library of security token standards, each covering a different aspect of security token functionality.

In order to combine these two standards, the additional constraints are specified.

operatorTransferByPartition

If the token is controllable (isControllable returns TRUE) then the controller may use operatorTransferByPartition without being explicitly authorised by the token holder.

In this instance, the operatorTransferByPartition MUST also emit a ControllerTransfer event.

Correspondingly, if isControllable returns FALSE then the controller cannot call operatorTransferByPartition unless explicitly authorised by the token holder.

operatorRedeemByPartition

If the token is controllable (isControllable returns TRUE) then the controller may use operatorRedeemByPartition without being explicitly authorised by the token holder.

In this instance, the operatorRedeemByPartition MUST also emit a ControllerRedemption event.

Correspondingly, if isControllable returns FALSE then the controller cannot call operatorRedeemByPartition unless explicitly authorised by the token holder.

Default Partitions

In order for transfer and transferWithData to operate on partially fungible tokens, there needs to be some notion of default partitions that these functions apply to. The details for how these are determined (e.g. either a fixed list, dynamically, or using partitionsOf) is left as an implementation detail rather than defined as part of the standard.

When transferring tokens as part of a transfer or transferWithData operation, these transfers should respect the invariant of partially fungible tokens, namely that the sum of the balances across all partitions should equal to the total balance of a token holder.

Interface

/// @title IERC1400 Security Token Standard
/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec

interface IERC1400 is IERC20 {

  // Document Management
  function getDocument(bytes32 _name) external view returns (string, bytes32);
  function setDocument(bytes32 _name, string _uri, bytes32 _documentHash) external;

  // Token Information
  function balanceOfByPartition(bytes32 _partition, address _tokenHolder) external view returns (uint256);
  function partitionsOf(address _tokenHolder) external view returns (bytes32[]);

  // Transfers
  function transferWithData(address _to, uint256 _value, bytes _data) external;
  function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external;

  // Partition Token Transfers
  function transferByPartition(bytes32 _partition, address _to, uint256 _value, bytes _data) external returns (bytes32);
  function operatorTransferByPartition(bytes32 _partition, address _from, address _to, uint256 _value, bytes _data, bytes _operatorData) external returns (bytes32);

  // Controller Operation
  function isControllable() external view returns (bool);
  function controllerTransfer(address _from, address _to, uint256 _value, bytes _data, bytes _operatorData) external;
  function controllerRedeem(address _tokenHolder, uint256 _value, bytes _data, bytes _operatorData) external;

  // Operator Management
  function authorizeOperator(address _operator) external;
  function revokeOperator(address _operator) external;
  function authorizeOperatorByPartition(bytes32 _partition, address _operator) external;
  function revokeOperatorByPartition(bytes32 _partition, address _operator) external;

  // Operator Information
  function isOperator(address _operator, address _tokenHolder) external view returns (bool);
  function isOperatorForPartition(bytes32 _partition, address _operator, address _tokenHolder) external view returns (bool);

  // Token Issuance
  function isIssuable() external view returns (bool);
  function issue(address _tokenHolder, uint256 _value, bytes _data) external;
  function issueByPartition(bytes32 _partition, address _tokenHolder, uint256 _value, bytes _data) external;

  // Token Redemption
  function redeem(uint256 _value, bytes _data) external;
  function redeemFrom(address _tokenHolder, uint256 _value, bytes _data) external;
  function redeemByPartition(bytes32 _partition, uint256 _value, bytes _data) external;
  function operatorRedeemByPartition(bytes32 _partition, address _tokenHolder, uint256 _value, bytes _operatorData) external;

  // Transfer Validity
  function canTransfer(address _to, uint256 _value, bytes _data) external view returns (byte, bytes32);
  function canTransferFrom(address _from, address _to, uint256 _value, bytes _data) external view returns (byte, bytes32);
  function canTransferByPartition(address _from, address _to, bytes32 _partition, uint256 _value, bytes _data) external view returns (byte, bytes32, bytes32);    

  // Controller Events
  event ControllerTransfer(
      address _controller,
      address indexed _from,
      address indexed _to,
      uint256 _value,
      bytes _data,
      bytes _operatorData
  );

  event ControllerRedemption(
      address _controller,
      address indexed _tokenHolder,
      uint256 _value,
      bytes _data,
      bytes _operatorData
  );

  // Document Events
  event Document(bytes32 indexed _name, string _uri, bytes32 _documentHash);

  // Transfer Events
  event TransferByPartition(
      bytes32 indexed _fromPartition,
      address _operator,
      address indexed _from,
      address indexed _to,
      uint256 _value,
      bytes _data,
      bytes _operatorData
  );

  event ChangedPartition(
      bytes32 indexed _fromPartition,
      bytes32 indexed _toPartition,
      uint256 _value
  );

  // Operator Events
  event AuthorizedOperator(address indexed _operator, address indexed _tokenHolder);
  event RevokedOperator(address indexed _operator, address indexed _tokenHolder);
  event AuthorizedOperatorByPartition(bytes32 indexed _partition, address indexed _operator, address indexed _tokenHolder);
  event RevokedOperatorByPartition(bytes32 indexed _partition, address indexed _operator, address indexed _tokenHolder);

  // Issuance / Redemption Events
  event Issued(address indexed _operator, address indexed _to, uint256 _value, bytes _data);
  event Redeemed(address indexed _operator, address indexed _from, uint256 _value, bytes _data);
  event IssuedByPartition(bytes32 indexed _partition, address indexed _operator, address indexed _to, uint256 _value, bytes _data, bytes _operatorData);
  event RedeemedByPartition(bytes32 indexed _partition, address indexed _operator, address indexed _from, uint256 _value, bytes _operatorData);


}

Notes

On-chain vs. Off-chain Transfer Restrictions

The 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 transferByPartition, transferWithData, transferFromWithData, canTransferByPartition and canTransfer functions accept an additional bytes _data parameter which can be signed by an approved party and used to validate a transfer.

The specification for this data is outside the scope of this standard and would be implementation specific.

Identity

Under 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.

There are various identity standards (e.g. ERC-725 (#725), 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 canTransfer 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.

Beyond this, the standard does not mandate any particular approach to identity.

Reason Codes

To improve the token holder experience, canTransfer 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.

Code Reason
0x50 transfer failure
0x51 transfer success
0x52 insufficient balance
0x53 insufficient allowance
0x54 transfers halted (contract paused)
0x55 funds locked (lockup period)
0x56 invalid sender
0x57 invalid receiver
0x58 invalid operator (transfer agent)
0x59
0x5a
0x5b
0x5a
0x5b
0x5c
0x5d
0x5e
0x5f token meta or info

These codes are being discussed at:
https://ethereum-magicians.org/t/erc-1066-ethereum-status-codes-esc/283/24

References

Copied from original issue: #1400

@adamdossa
Copy link
Author

From @expede on September 10, 2018 19:55

👍👍👍 This looks super awesome! I previously worked for a security token company, and am very, very happy to see this work being done 🎉 We also did some preliminary open work in this general space with ERC-902.

I'm the primary author of ERC-1066 (Hello! 👋) As of Sept 1, we're throwing a ton of time and energy into the ESC project (growing an FOSS team, my time at 100% for at least the next several months, we're in the FOSS track at the Tachyon Accelerator, etc). Expect big things 😉

Application-Specific Codes

The 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).

The 0xA* category range allows people to map their custom codes into the standard. This may or may not fit what you're thinking of using custom codes for. It may warrant more discussion, and at minimum some examples on our end to better describe that system.

Use Case Abstraction

Protocols are essentially abstractions over common use cases. We're doing a bunch of R&D around filling in the currently empty ranges in appropriate, flexible, reusable ways. Security tokens will almost certainly be a widely used standard, and common patterns will inspire other work in the ecosystem (like ERC20 -> ERC721).

We're gathering data from as many people as possible so that we can design the most useful code scheme. I'd love to hop on a call (phone or video), email thread, or even over at EthMagicians. We're going to be running regular community hangouts as well. Let me know what works for you!

#1400 (comment)

@adamdossa
Copy link
Author

From @darioAnongba on September 11, 2018 10:33

Awesome! I am also currently reviewing this EIP, looks good so far.

#1400 (comment)

@adamdossa
Copy link
Author

From @0age on September 11, 2018 15:18

Nice work! This is very thorough and addresses many of the most pressing issues concerning compliant securities tokens. One observation (and I doubt I am alone in this determination) is that this EIP comes with a great deal of complexity. Now, much of that is surely inherent to the problem space, but when it comes to ERC proposals in particular it's apparent that keeping it simple is of utmost importance, both for promoting widespread adoption and for encouraging secure best practices (and of course leaving the door open for extensibility). With that in mind, here are a few contrasting viewpoints:

  • A ton of the complexity is derived from the logic around tranches, and setting, managing and transferring between them. The idea of "partial fungibility" seems a bit disingenuous - either an asset is fungible or it is not. Obviously, securities DO often have tranches and so should support it, but in cases where they DON'T, this pattern is going to add a lot of overhead (both gas and extra headaches). Why not just implement tranches as separate tokens (TOKEN-A-CLASS, TOKEN-B-CLASS, etc.) with their own logic, permissions, and balances, then issue, aggregate, and convert between them as needed? Maybe this portion of the EIP could be broken out into its own EIP, and tranchedSecurityToken could then attach to a number of tokens representing various classes where applicable and provide the various getters, setters, and view functions laid out in this section, including its own balanceOf & totalSupply methods that sum each referenced tranche / class.
  • The provision requiring forced transfers could prove a poison pill for the proposal, and at a minimum will tend to politicize the debate around this standard and detract from the technical considerations. It also requires much of the ERC-777 functionality as structured now, but ERC-777 support is designated as optional (and should be - there are not many projects implementing the full spec in the wild as of yet). Why not just split it off into a dedicated EIP for forceableSecurityToken or the like?
  • If securities tokens prefer to delegate the management of metadata and transfer permissions to an external contract or outside jurisdiction, there is still a great case for providing checkSecurityTokenSend directly from the token (I like canTransfer and canTransferFrom but that's just one opinion 😉). However, the requirement to be able to set and modify metadata, including at the time of transfer, right from the securities token could prove onerous and inefficient in many of those instances.

Basically, a slimmed-down proposal containing the key sections of this EIP would be much easier to build widespread consensus around. The goal is to promote interoperability between a diverse ecosystem, not full compliance for every conceivable securities token in every potential jurisdiction. From there, incremental ERCs could continue to enhance the features (or bugs, according to many crypto-maximalists 🐛) available to protocols around securities tokens - and of course any particular securities token could always go beyond the initial requirements.

Also, a small aside - unless I'm mistaken, the implementation is currently susceptible to integer overflow & underflow vulnerabilities.

Awesome work and thank you all for putting this proposal together!

#1400 (comment)

@adamdossa
Copy link
Author

From @dmdque on September 11, 2018 22:18

  • I agree with 0age about the complexities of tranches. It's an ambitious effort, but tranches feel like a secondary priority, and would require a base security token standard to be finalized first anyway. I think a simplified version of this EIP will go much further.

  • I love that you included EIP1066 here, they work really well together.

  • Forced transfers are an important topic which needs to be explored further. This is a can of worms from an exploit perspective, but a necessary evil for adoption. Restricted transfers are straight-forward because of checkSecurityTokenSend (+1 for canTransfer) which allows checking ahead of time. Should we limit the transfers that can be forced to make them more predictable? I think there's value in exploring this.

  • Should transfer freezes be considered as well? The crypto enthusiast in me doesn't want this, but trading halts are a common occurence.

  • A note on the one-way nature of issuance: I consider this a "soft requirement" since it's difficult to enforce and impossible to verify on-chain. Soft requirements are too easily avoidable in practice, which causes a rift across implementations.

    • It reminds me of the many ERC20 "SHOULD" requirements that weren't implemented across the board, and resulted in tokens being "mostly" ERC20. (eg. returning false rather than reverting for transferring with insufficient balance.) This caused annoyances downstream, where token interaction proxies are required to bridge the gap.
    • There may be value in removing this since projects are likely to walk their own path. Future applications may incorrectly assume that issuable is one-way because it's in the standard, resulting in bugs and headaches. Also, there are valid reasons to issue again, such as secondary offerings. (It doesn't suffice to leave issuable on because it's hard to predict that a secondary offering will be had.)

Overall this is a great start. Companies are run by people who make mistakes, and need wiggle room. A big challenge for security tokens is the lack of flexibility on the blockchain. I think this EIP addresses this with the forced and restricted transfers.

#1400 (comment)

@adamdossa
Copy link
Author

From @zingleton on September 12, 2018 03:23

I think this is great stuff.

I like the tranches. I am new to this discussion and I have no idea what the original use case was, but I can make an informed guess. They are the best way that I have seen to implement US Reg D/Reg S rules. Under the Reg S rule, I can sell US securities to a non-US buyer, and they can trade those securities, but they can't sell them back to a US buyer until one year has passed from the issue date. If the Reg S sale from a particular date is in one tranche, we can track and enforce this rule. Almost any other way to do it is more complicated, and wrong. So, tranches are actually a simplification in this case.

Reg D lockups should also be handled by tranches for a particular issue date. The Reg D rules say that a US buyer of a private security should hold it as "restricted" for a year. This is almost always implemented with a lockup on the buyer, where the buyer can't sell the security until one year has passed. However, the lockup implementation is not accurate. A fund with more than $100M in assets under management (QIB or Qualified Institutional buyer) can buy the Reg D securities before the lockup has expired. They get this privilege from "rule 144a". The restriction on resale to anyone BUT a QIB continues for the remainder of the year - as measured by the properties of the security issue tranche, not the buyer. These rule 144a privileges are socially offensive, in giving special privileges to wealth, but they are likely to be quite important in the real world of US private market securities.

In this use case, multiple tranches represent the SAME security. That's important. They are not like the tranches of an asset backed security that are designed to be different. They are the same security with different transfer rules. They all add into the same cap table percentages for voting and distributions. So, splitting them into different tokens screws up all the numbers. Some people are splitting one security into different tokens so they can track a Reg S issue. This is a bad solution and a lot more complicated to put back together into relative percentages than just implementing these tranches. The tranches are a simplification.

You do want the ability to collapse two tranches into one. They represent the same security. For example, Reg D and Reg S tranches issued on different dates can often be collapsed when the US restrictions expire in a year.

The tranches can themselves be simplified. If they all represent the same security, then I can't see why you would want different permissions and operators. That feature could be eliminated. It would make sense to go through and remove extra tranche operations and features.

Security tokens need to be pausable (freeze transfers). Under any reasonable disclosure regime, if a company finds out some big news that will affect their traded securities, they should freeze transfers until they can make a public disclosure. If they don't they WILL get sued in the US. Lawyers file thousands of shareholder lawsuits every year alleging they bought securities without knowing some important thing that the company had not revealed yet. That's their standard "securities fraud" complaint about anything they don't like. A blockchain mechanism that allows issuers to "pause" or block transfers right on the token is a big step forward for securities that are traded in multiple venues and OTC. Maybe this doesn't need to be in this spec but it does need to be somewhere in the implementation. I think "pausable" is pretty common in the Zeppelin-derived ERC 20 implementations. So, I guess that shows it doesn't need to be in the standard. The standard needs to describe the functions that would be used by handlers like exchanges and wallets to deal with multiple types of securities. Maybe it doesn't need to describe features (like pause/freeze) that are only used by the issuer.

Forced transfers are required for real security. If an issuer sells securities to grandma, and she dies and leaves no key, the issuer still needs to deliver the securities to her estate under most securities regimes. Issuers have to be able to print up a new stock certificate. Maybe it doesn't have to be in the standard, but it has to be in the implementation. This standard makes it easy to add multisig governance to that, which is how we handle it. However, forced transfer is also something that the issuer does (with multisig arbitrators), and not the exchanges and wallets that rely on a standard.

#1400 (comment)

@adamdossa
Copy link
Author

From @0age on September 12, 2018 08:58

Great information, @zingleton - thanks for laying out lots of concrete details related to US Reg D / Reg S. You make a strong case for utilizing tranches to enforce these regulations, but i’m not yet convinced that it should be a mandatory part of the global standard - what about all the jurisdictions that don’t require adhering to these regulations?

Maybe a good place to start would be to specify a much simpler permissionedToken interface that addresses the following requirements:
• MUST have a standard interface to query if a transfer would be successful and return a reason for failure.
• MAY be able to modify metadata at time of transfer based on off-chain data, on-chain data and the parameters of the transfer.
• MAY require signed data to be passed into a transfer transaction in order to validate it on-chain.
• MUST be ERC20 compatible.
• SHOULD be ERC721 compatible.
• SHOULD be ERC777 compatible.

Then, these interface requirements can be utilized and expanded on by a wide variety of securities tokens (and other projects), including a securities token standard with all of the bells and whistles that a US-compliant securities token would need (and then optionally overloading the transfer check with a tranche argument as required would be a natural choice).

Concerning forced transfers, “grandma loses her key” is a strong analogy as well - i’m just pointing out that this will be a contentious issue that may benefit from isolation from the rest of the proposal.

#1400 (comment)

@adamdossa
Copy link
Author

From @darioAnongba on September 12, 2018 09:30

I agree with @zingleton on this:

The standard needs to describe the functions that would be used by handlers like exchanges and wallets to deal with multiple types of securities. Maybe it doesn't need to describe features (like pause/freeze) that are only used by the issuer.

The standard is needed for interoperability between different entities, potentially all across the globe. Implementation specifics shouldn't be part of the standard. Now, the question is, are tranches needed in the standard to facilitate interoperability? (even if using a single default tranche for tokens that don't need it). I personally believe that yes, tranches are necessary in the standard. This would ease integration instead of having to deal with multiple token classes.

#1400 (comment)

@adamdossa
Copy link
Author

From @fubuloubu on September 12, 2018 13:54

I believe the tranches approach is actually better than having separate classes of tokens. Both are equally viable options, but there might significantly complex reclassification rules for a token to change tranches, and the properties of that transfer would be more difficult to evaluate from a (software) security standpoint than if the logic were handled internal to the contract.

I also think this semi-fungible concept is very useful from other standpoints: one could imagine a reputation token that had different subcategories depending on how it was earned. Being able to subcategorize a token based on different properties a subset of holdings should have is very interesting. I think this should be separated into a different, dependent standard and developed separately to reduce the complexity of this proposal.

Just picture a pie chart of your holdings, denominated by tranches. Very useful concept.

I also think there should be a getAllTranches or similar that returns all possible tranches any holder in the contract could have. Right now, it is dependent on the holder to delineate what they personally could have, so I could see this as useful.

#1400 (comment)

@adamdossa
Copy link
Author

From @zingleton on September 12, 2018 15:21

It might be possible to hide the tranches so that you would have an option to:

  • not use them (the default tranche is an implementation of this)
  • include them in the security, but have the token code itself figure out how to use them. On "send", the script would try to figure out what tranche can be sent (has an appropriate balance, passes transfer rules). This would be an extension of the idea of a default tranche to a default send.
  • Use them directly. I think they should appear in the standard because exchanges and wallets will want to understand what tranches are available.

#1400 (comment)

@adamdossa
Copy link
Author

From @seathemc on September 13, 2018 14:11

This was really cool to read through. Couple of questions:

  1. Is there no room to include that there must be some kind of consideration/standard for the taxation of these securities - perhaps included in the metadata?
  2. Also, what about a communication channel between the issuers, and the purchasers? One of the mainstays of public and private securities is that an issuer is meant to build a 'community' with their investors/shareholders - and there should be an open line of communication. In line with the thoughts by @darioAnongba, is it not appropriate to create standards for exchanges to follow to create some kind of communication channel/voting mechanism between issuers and shareholders/STO purchasers?

#1400 (comment)

@adamdossa
Copy link
Author

From @zingleton on September 13, 2018 14:41

I like the idea that the security standard provides some basic support for both public docs (as included) and private messaging.

Messaging would go into a different type of standard with a more general mission. Basically, the messaging that is needed is a global queue where you can post encrypted messages for an Ethereum address, or content hash pointers to encrypted messages. They would be posted for a specific public key, from a specific address. For this to work, you would also need a database that matches an Ethereum address or similar blockchain address to a full public key. Probably you would accept a variety of addresses to go cross-chain. There must be implementations of this since it is such a common need. The security token standard would then only require a way to show the address of an issuer or other party that would send and receive messages.

Voting would probably go into a different but similar queue. What you want is proxy assignment and proxy voting AKA "liquid democracy". That would not be part of the standard and it doesn't need to be decentralized.

#1400 (comment)

@adamdossa
Copy link
Author

From @darioAnongba on September 13, 2018 16:57

Is there no room to include that there must be some kind of consideration/standard for the taxation of these securities - perhaps included in the metadata?

I think you answered your own question. Taxation cannot be directly written in the standard as it is specific to jurisdictions

Also, what about a communication channel between the issuers, and the purchasers? One of the mainstays of public and private securities is that an issuer is meant to build a 'community' with their investors/shareholders - and there should be an open line of communication. In line with the thoughts by @darioAnongba, is it not appropriate to create standards for exchanges to follow to create some kind of communication channel/voting mechanism between issuers and shareholders/STO purchasers?

Would be interested to know if an EIP exists for that!

#1400 (comment)

@adamdossa
Copy link
Author

From @tomohiro-n on September 13, 2018 17:27

Great work!

I like the tranche's extensibility. Even if the token has solely default tranche at first but it may be going to have another.

On the other hand, I'd like to hear secondary markets' thoughts on this tranches-or-tokens discussion.
One thing which may go very complex is that prices can be set per tranche, per group of tranches, or per token. I don't think It would be necessary to include the practical manner in the standard but we may want to use tranches on the condition that all tranches under the token should have the same price? In other words, issuing another token may be better if we expect them to have different prices.

#1400 (comment)

@adamdossa
Copy link
Author

From @pakaplace on September 13, 2018 17:28

Really high-quality thread here. We at Meridio have been refining our security token contract- an upgradeable security token issued per-asset with modular validation checks on transfer(). We actually tokenized our first asset in Brooklyn just a few months ago.

Tranches

There's clearly a strong business case for closely resembling the nuances of security classifications via tranches, but also more complexity on validating transfers and interoperability (e.g. integrating with exchanges). The more I read through this thread (thanks @zingleton), I’m increasingly sold on the benefit of tranches.

While tranches may not be necessary for classes of securities (e.g. common vs preferred equity, which I think would be better served by a separate token issuance), tranches work well for different filings for the same underlying security e.g. Reg D for U.S. investors and Reg S for foreign, when additional securities are offered for the same class, or for allocating pools of tokens within the larger issuance for daily trading limits. The fundamental concept of having a token be “partially fungible” within the same security issuance is important because that’s how they operate in exchanges today.

Given their benefit but also the introduced complexity, I lean towards having one standard that would provide security tokens for individually issued common vs equity securities and one that would include tranches and could be used for Reg D/S securities. Both ERC-20 etc. compatible, of course.

###Additional data field on send()
I’m leaning against the idea of a _data input for an e.g. signed attestation based on off-chain data by the broker-dealer. I fear the coordination effort between exchanges/broker-dealers for reading and validating off-chain data would be too difficult. I’m in favor of keeping transfer validation on-chain whenever possible and limiting the attestor’s potential for error. I would need to see some simple and clever examples in practice of _data

checkSecurityTokenSend()

I’m with the other commenters that this is quite the mouthful, but otherwise, it’s great to see various security token projects (e.g. PolyMath, Harbor, Meridio) starting to converge on modular checks on transfer(). I would second the recommended language change to checkTransfer() or otherwise suggest validateTransfer().

Status Codes

I appreciate the analogy given in ERC-1066 of Ethereum Status Codes resembling HTTP status codes. Our team at Meridio would definitely support more industry convergence on error codes (ERC-1066), application specific codes, and reason coding (defined here).

Token Metadata

Regarding an inheritable metadata interface, I’d support either this (get/setDocument()) or a separate registry contract to get/set metadata for each contract address. In addition, perhaps a separate thread is needed for industry-specific metadata coding. At Meridio, we’re currently using traditional industry code standards such as NAICS and RESO’s data models specifically for real estate assets.

cc @corbinpage, @DavidConroy, @ashadakshi and the rest of the Meridio Team team for contributing.

#1400 (comment)

@adamdossa
Copy link
Author

From @jllaw on September 13, 2018 18:16

@0age

"Why not just split it off into a dedicated EIP for forceableSecurityToken or the like?" That's interesting; I've long been a begrudging fan of forced transfer (not ideal, but necessary for regulated tokens), so it always seemed like it had to be part of ERC1400. I'm trying to think if there's ever a use case where one wouldn't actually want forced transfer in a regulated token; if there aren't many times where it wouldn't be required, I'd assume we'd leave it in as part of 1400; otherwise, separate might make some sense.

"Basically, a slimmed-down proposal containing the key sections of this EIP would be much easier to build widespread consensus around." True. It's a bit difficult to figure out how slimmed down to go versus not so that those dealing with ERC1400 have reassurance that it supports all the expected functionality of regulated security tokens.

#1400 (comment)

@adamdossa
Copy link
Author

From @fubuloubu on September 13, 2018 18:35

It's a bit difficult to figure out how slimmed down to go

I think the partial-fungible token concept is a very clear example of how to reduce complexity. If you separate that, the security aspects of this proposal are easier to evaluate and in fact makes it possible for implementation via a PFT or multiple tokens, or even ERC20, if desired.

I would argue this proposal is really 3 related proposals in one:

  1. Variable supply (ERC20 suggests guidelines but doesn't standardize them IMO)
  2. Partially Fungible Tokens
  3. Custodialship (e.g. forced transfers)

Each has their own use cases outside of securities and could benefit from coordinated conversation instead of pushing the security use case into one EIP, leaving the other use cases to implement their own standards without the extra stuff they don't need.

#1400 (comment)

@adamdossa
Copy link
Author

From @pabloruiz55 on September 13, 2018 19:16

First of all, thanks for all the comments. Happy to see all the conversation going on over this proposal.
@fubuloubu after reading all the feedback, we are seriously considering splitting the EIP in a few pieces and have separate discussions given there are some topics that are more controversial than others (Forced Transfers, looking at you 👀 ).

#1400 (comment)

@adamdossa
Copy link
Author

From @jllaw on September 14, 2018 08:44

@pabloruiz55 There's merit in that, but if we split up into something like 3 EIPs that really need to work together, will we come into the scenario where many in the industry start saying something like, you must be ERC20 and ERC777 and ERC1400 and ERC-XXX and ERC-YYY for us to accept you? If that's the case, then wouldn't we essentially be better off just having it all covered in ERC1400? Taking forced transfer as an example, if essentially all security tokens (and I'm not sure that it is 100%) would require forced transfer, then wouldn't we want to include that in ERC1400 instead of breaking it apart into a separate optional EIP?

#1400 (comment)

@adamdossa
Copy link
Author

From @0age on September 14, 2018 10:30

@jllaw - splitting up this EIP wouldn’t fragment the ultimate canonical securities token EIP. Once the constituent EIPs are well-specified, the specification for ERC1400 compatibility becomes really straightforward: it just needs to state which EIPs it requires and how they intersect. From there, industry members can just require ERC1400 as shorthand for requiring all the EIPs it implements.

However, splitting it up would make securities tokens more compatible with a broader ecosystem, particularly with permissioned tokens that don’t have all the requirements of a full-fledged security. There are many interesting applications for utilities tokens that require unique identities, like governance tokens with voting mechanisms that go beyond 1 token : 1 vote. Some, but not all, of the interfaces needed for securities tokens will overlap with those needed by projects like these, and how cool would it be to have one method for checking if a given token transfer will go through?

(Still like canTransfer the best - seems the most like the OG, ERC20 😁)

In the case of securities tokens with tranches, I think this should in the default case check that the transfer is ok from some tranche or combination thereof (a default tranche specified by the securities token would be a sane choice) without needing to specify the tranche. To expect every interfacer to know details about all the tranches of all the various securities tokens seems unrealistic. Then, an extension to this method like canTransferFromTranche would provide more granular checks for those interfacers who require them.

#1400 (comment)

@adamdossa
Copy link
Author

From @rudolfix on September 14, 2018 11:32

Good to have this discussion started! Security tokens definitely will extend current token ecosystem and some standardization is very needed.

With this particular RFC I have a problem that it packs every required functionality in the token itself. If we are designing a protocol we should decide first what should go to the app layer and should not be mandatory part of standard. Over-defined protocol will be extremely limiting in the future.

Example: different stock classes are listed separately and have different market value on secondary markets because they give different rights to their holders. They are not fungible and naturally they represent separate tokens. Now I get that there could be a need to define something like token container that groups tokens form the same issuer that are connected via definable set of rules (like how to convert one token into another) but it's not a part of a token. it is rather part of token controller which represents issuer (for example a limited company with typical governance). Every issuer can deal with it as they wish. Some want one stock class and single token. Some will issue many tokens of different classes. Some may use this tranche proposal. Now we can have a standard token container for this things. However if it is implemented inside with separate tokens or with tranches should be irrelevant. By mandating it to be part of the token we are limiting future developers of apps based on security token standard to particular implementation, while I for example do not even see tranches as essential part of security token ecosystem.

Now what I think we should have as security token is something that is building and extending existing token ecosystem: is lean, simple, ERC-20 compatible, leaves as much as possible in the app layer and is useful beyond security token domain. This is my take on what we should do

  • Security tokens must be legally binding tokens. Security tokens give holders off-chain rights and possession of a token should be easily enforceable off-chain. This RFC does a first take on that but it's really a separate domain that should be a separate standard. I totally see something like "legally binding smart contract" with standard interface to irrevocably link contracts to legal documents, sign them, retrieve who signed and with which smart contract state.
  • Token controller. Please look at MiniMe token to see how powerful concept it is. We should separate token which is about ownership rights from token governance (like token transferability, vesting, lockins, forced transfers etc.). It's better to standardize simple token - controller interface than trying to define app layer stuff in the token! This way you have endless possibilities how this governance is implemented and you keep your token simple.
  • Security tokens must enforce several rights that are earned via their possession. For example right to dividend, voting rights, information rights etc. are not transferred when you trade your token. You are still legally entitled to your past dividend. There is already extremely elegant and powerful solution to this in the MiniMe token (balanceOfAt and totalSupplyAt) which also let's you do tons of other things (Aragon is using this for example).

Now the thing I like about current standard is to have canTransfer as part of the token because it's simply practical. In scheme above token controller can answer this questions via standard interface but a little shortcut is not bad.

I summarized all of this with some code samples here, you can read this is you have a few minutes: https://blog.neufund.org/good-protocols-how-to-properly-standardize-security-tokens-95ff83c81c4a

#1400 (comment)

@adamdossa
Copy link
Author

From @zingleton on September 14, 2018 13:52

This discussion has momentum and it is pulling together separate groups to work on a standard. I want to learn more from the people on this thread. Should we schedule some meetups? I have heard that this proposal started with a small meeting that Polymath organized in Barbados. Now we have more participants that are interested in contributing. We can meet up at Ethereum or security token events. Maybe we can start with a meetup in New York around October 5, when some people will go to the "Security Token Academy" event. Maybe we can suggest similar meetups in Europe and Asia.

#1400 (comment)

@adamdossa
Copy link
Author

From @seathemc on September 14, 2018 14:00

Can it be virtual? We are working on mobile security tokens based out of Nairobi with mobile money. Happy to lead a session for the community too. Marvin Coleby Founder Raise m: 514 430 1973 w: raiseimpact.io

On Sep 14, 2018, 3:53 PM +0300, zingleton @.***>, wrote: This discussion has momentum and it is pulling together separate groups to work on a standard. I want to learn more from the people on this thread. Should we schedule some meetups? I have heard that this proposal started with a small meeting that Polymath organized in Barbados. Now we have more participants that are interested in contributing. We can meet up at Ethereum or security token events. Maybe we can start with a meetup in New York around October 5, when some people will go to the "Security Token Academy" event. Maybe we can suggest similar meetups in Europe and Asia. — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

#1400 (comment)

@adamdossa
Copy link
Author

From @thegostep on September 14, 2018 14:17

Thank you all for the great response! It is thrilling to see hear from so many voices in the space and clear that many are thinking about these issues. My job is to involve a diverse set of opinions from across the ecosystem and shepherd the conversation towards some sort of consensus.

We have scheduled a community call for Monday, Sept 17th with @bmann from ETHMagicians and @expede from ERC-1066 to have a public discussion.

To participate in the call, please sign up here.

#1400 (comment)

@adamdossa adamdossa changed the title WIP STS EIP 1400: Security Token Standard Sep 14, 2018
@adamdossa
Copy link
Author

adamdossa commented Sep 14, 2018

@expede

With regards to the return values of checkSecurityTokenSend we were thinking that in addition to the ERC 1066 byte code, the contract might want to give a more granular response (hence the additional bytes32 return value).

As an example, suppose that transfer failed due to:
0xA3: Transfer Blocked - Sender lockup period not ended
then we may also want to return the actual lockup period end date using this bytes32 return value.

So the byte code give the general response (which could be used on-chain for example) and the bytes32 gives additional data that could be used in e.g. a dApp to show the user more context.

@zingleton

Thanks for providing so much concrete detail around US regulatory rules - very useful for the discussion!

It should be possible to ignore the internals of tranches and instead use the ERC777 (or ERC20) send / transfer functions which would use default tranches and on-chain code to determine how to deal with tranches.

This is what we were trying to describe in the "ERC20 / ERC777 Backwards Compatibility" section.

If you go down this route, then tranches just become an internal implementation detail, but if you want to implement the full ERC 1400 specification you can do which would give users (e.g. token holders, exchanges) more flexibility if they did want to operate on the tranche level.

@fubuloubu

Regarding getAllTranches there is a tranchesOf function that returns the tranches of an individual token holder.

I can see that getting all tranches (across all users) may have some use cases, although it may make implementations a bit more complex. There is also no guarantee in the standard that the same tranche key across different users would be attached to the same metadata, so tranche keys should generally be interpreted along with the token holder address (there may be implementations where this is not true).

@seathemc

Taxation is interesting - possibly this should exist as a separate standard, or as an implementation detail. As an example we recently authored a dividend module which withholds appropriate tax.

I love the idea of a communication channel, and communication between issuers and their security holders is critical - will think more about this ;-).

@tomohiro-n

We have spoken to some exchanges. Currently they are generally building on top of ERC 20 which makes sense as it is the industry standard for tokens. This EIP is an effort to move the conversation on from ERC 20 to a more specific token specification for securities, but we would expect discussion and adoption to take some time as everyone works through the limitations of ERC 20 and thinks about different ways to address these (of which this EIP is one proposal).

@rudolfix

Really appreciate your input on this EIP - there is lots to digest and definitely lots of ways to skin a cat here. We will keep thinking about how best to decompose the standard into more digestible chunks which are less constraining.

With regard to using multiple tokens with a container, I guess this could be the way that you implement tranches (i.e. a separate token per tranche) in which case the partially fungible token standard still provides a standardised way to interoperate across a container of tokens.

@ALL

Switched over to canSend from checkSecurityTokenSend.

@adamdossa
Copy link
Author

In case it got lost in the issue migration, as per @thegostep there is a community call to discuss this issue kindly organised by @bmann from ETHMagicians and @expede from ERC-1066 #1066.

To participate in the call, please sign up here.

@pabloruiz55
Copy link

@zingleton we are going to be at Devcon and proposed a talk around Securities Tokens for the Council of Prague the days prior to the main event. You can join here: https://hackmd.io/DaJhrasLQteUk3IwX5bQAg?view

@rudolfix
Copy link

thanks for listening to our feedback. Looking at the many voices that have chimed in here, it's apparent that the security token ecosystem is bigger and more diverse than maybe any of us realize. There are a number of security token issuers and many of them hail from different jurisdictions and are therefore subject to varying regulations. This impacts how securities are issued and traded and makes it even more imperative that we create a globally-accepted standard that is flexible enough to adapt to these changing circumstances. From my perspective, it appears that it's too soon for us to be discussing a particular interface and instead we need to take a step back and consider the various perspectives on the table.

Just as an example, we at Neufund have been working hard on the issuance of security tokens for more than two years. Naturally, we have certain views as to how it should be standardized, some of which I elaborated on in my comments above. I am sure we are not the only ones, and we need to allow all voices to be represented. That said, we are very excited that this discussion is taking place and we want to push forward a security token standard that is sensible for all parties, regardless of geography or differences in legal jurisdictions. I think there are many other projects on Ethereum that are willing to do the same.

While it sounds like there were some discussions had at the meeting in Barbados a few months ago, many of us learned about this meeting after the fact from the media, similar to how @zingleton described. In fact, my understanding is that the only major security token issuer represented was Polymath. Obviously, if we want to create a global standard we need input from players like Harbor, Securitize and TrustToken in the US, as well as European and Asian issuers like Neufund, Swarm Fund, SmartValor, Own, Blackmoon, just to name a few.

My proposition would be as follow:

  1. Create an alliance similar ERC725 alliance (https://erc725alliance.org/) where fundamentals of the standard could be discussed. (what's cool is that the audience seems to be similar including @frozeman, who has been one of our key advisors from the beginning and a prominent Neufund community member). Every project that has commented on this thread, plus everyone else we can think of, should be invited to this alliance.

  2. Organize a satellite event like a workshop at Devcon4 that will be open to all of us and where we can discuss these matters as an alliance, knowing there will be good representation from all sides.

We still have time to get this right, and to ensure everyone is heard. Let me know what you think of the above. We will also join for the call on Monday and can discuss there too.

@seathemc
Copy link

seathemc commented Sep 14, 2018 via email

@gauthierpetetin
Copy link

Hi all,
Here's a public repo we've created to share an ERC1400 implementation we've developed at ConsenSys:
https://github.com/ConsenSys/ERC1400

@aapeliv
Copy link

aapeliv commented Jan 27, 2019

@adamdossa Interesting! This is very good stuff! I feel it'd make sense to have a isControllableByPartition (and other relevant functions for partitions) to mark certain partitions (tranches) as controllable and others as not? I think it'd really help the standard to have more of this type of flexibility and granularity, which surely comes up in certain use cases.

@adamdossa
Copy link
Author

Some interesting proposals from the Aztec team on confidential transfers at:
#1723
#1724

@kgcorps
Copy link

kgcorps commented Mar 18, 2019

Question: Is there a good reason for methods of IERC1594 to return "void"? I'd expect it to be inline with transferByPartition in a sense that it would return bytes32 indicating success or error state of the transfer.
I.E.
function transferWithData(address _to, uint256 _value, bytes _data) external returns (bytes32);
function transferFromWithData(address _from, address _to, uint256 _value, bytes _data) external returns (bytes32);
Otherwise it seems like a glaring consistency issue accross different ERC's.
This is a suggestion and question at the same time. I'm currently working on implementation so feedback on this question/suggestion is most welcome, thank you!

EDIT:
Upon further inspection of ERC I understood, that my question is not exactly correct, however, I still believe that returning execution state might be good practice? As in code indicating whether transfer was a success or something failed.

@RobertoSnap
Copy link

RobertoSnap commented May 15, 2019

With use of ERC-1643, can one remove the event Document(bytes32 indexed _name, string _uri, bytes32 _documentHash); from and rather rely upon event DocumentRemoved(bytes32 indexed _name, string _uri, bytes32 _documentHash); event DocumentUpdated(bytes32 indexed _name, string _uri, bytes32 _documentHash); from 1643

@isingh108
Copy link

It is very good EIP. I vote for it.

@tpmccallum
Copy link

Hi,
I am wanting to add security token smart contract ABIs to an Ethereum Smart Contract Search Engine (ESCSE) [1]. The ESCSE indices are underpinned by contract ABIs. It was easy to load in ERC20 because I found this official ABI specification [2]. Could you please point me to a similar official specification if one exists. Thank you so much.
[1] https://ethereum.search.secondstate.io/ethIndex.html
[2] https://github.com/ethereum/wiki/wiki/Contract-ERC20-ABI

@MaxBinnewies
Copy link

Can someone explain to me the difference between an "operator" and a "controller"? It seems that both these role are allowed to transfer tokens for other token holders, if authorised.

@LiuYuPeng1101
Copy link

I have a question about why ERC1400 is compatible with ERC20?

@jameshiester
Copy link

Can someone explain to me the difference between an "operator" and a "controller"? It seems that both these role are allowed to transfer tokens for other token holders, if authorised.

Based on the consensys implementation, it would appear to me as if the controller is the "owner" of the token contract, and can therefore conduct forced transfers, set documents, etc, whereas the operators are authorized by the token holders to conduct transfers on their behalf. Can someone please confirm this is correct?

@mudgen
Copy link
Contributor

mudgen commented Jul 9, 2020

Consensys Diligence recently made a suggestion or recommendation that Codedefi's implementation of ERC1400 use the Diamond Standard to handle the problem of maximum contract size limit. Would it make sense to mention the Diamond Standard in ERC1400 as a possible solution this problem?

Also, of note, ERC-1155 Multi Token Standard, mentions using ERC1538 for upgrading ERC-1155 contracts. The Diamond Standard is an improved version of ERC1538, and like ERC1538 it can be used to create upgradable contracts. Also note that diamonds can be immutable or upgradeable, depending on how they are implemented.

Diamonds are ideal for contract systems like tokens that deal with a lot of state and code, because they help you organize your code around contract state without running into the max contract size.

An introduction to the Diamond Standard is here: Understanding Diamonds on Ethereum

@ahmazza
Copy link

ahmazza commented Aug 19, 2021

Hi everyone, Adrian from SignersTech / PayOnTerm here.

Just wondering, has any of you seen or worked on a similar security token implementation but based on ERC-1155 (or any other NFT standard) instead of ERC-20 ?
If none, is anyone interested in working together to create one?

I'm thinking of use cases where creating a separate smart contract for each token seems a bit of an overkill in terms of compute (and cost), and where many different security tokens (issued by various issuers or at various points in time) may share the same ruleset for interoperability

@mudgen
Copy link
Contributor

mudgen commented Dec 8, 2021

I would love people's thoughts about implementing ERC1400 using an upgradeable, transparent contract that implements ERC1538.

Hey @mudgen - I just took a look at 1538 - really nice pattern. Def. possible to implement ERC1400 as an upgradable, transparent contract - we've been running into lots of issues related to contract size in our current security token implementation, so very interested in creative ways to split it up! The functions fall into relatively nice groupings to split into separate contracts.

Great! Please consider using EIP-2535 Diamonds now which is based on ERC1538 and is better.

@github-actions
Copy link

github-actions bot commented Jun 6, 2022

There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review.

@github-actions github-actions bot added stale and removed stale labels Jun 6, 2022
@ethereum ethereum deleted a comment Jun 6, 2022
@MicahZoltu
Copy link
Contributor

Closing this issue for housekeeping purposes. People are welcome to continue discussing in this thread, but for additional visibility an EIP should be created or the conversation should be migrated to https://ethereum-magicians.org/

@mdesousa
Copy link

mdesousa commented Nov 5, 2024

hello @adamdossa, @pabloruiz55, @frozeman and @thegostep,

we noticed ERC-1400 last week and think that it may be a good fit for our project. we are working on a solution to bring affordable credit to millions of financially excluded small businesses and independent workers around the world.
i was wondering if you could point us to a reference implementation for this ERC, or any of related ones (ERC-1410, ERC-1594, ERC-1643, ERC-1644). Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests