Closed masonicGIT closed 2 years ago
This seems very similar to #902?
902 uses a check
function (it's broader than just security tokens, but effectively this is the same as detectTransferRestriction
).
No worries either way, but happy to discuss updates into 902 if you found something missing in it.
Thanks for taking the time to write up and submit this as an EIP!
@bmann Thanks for chiming in!
Looks like #902's TokenValidator
contract shares more similarities to Harbor R-Token's RegulatorService approach. We include an R-Token integration example here! 😄
In ERC1404, detectTransferRestriction
is meant to live on the token contract itself, in there you could easily kick off the call to validate
(what looks to be one of #902's "validation helpers") and achieve a similar result.
Some questions (might be dumb):
detectTransferRestriction
? Just to make sure as there's a bit of cognitive disonance about ERC-20.detectTransferRestriction
?). I might off with this one on the purpose of this (though in that case pointers and clarifications welcome).Hi, I'm very interested in using this standard for a governance project with regards to access control. Anybody looked into how this would work with Giveth's mini-me contract?
@Graeme-Code, I have not personally used the MiniMe pattern but at a cursory glance of Giveth's repo, it seems you would need to use a version of the MiniMeToken.sol
contract modified to implement ERC1404 -- the place to look is function doTransfer()
on this contract.
If there is considerable interest in this use-case I would be happy to add an implementation to our examples repo.
Thank you for the quick response. Running some tests internally and getting consensus on the idea. Will let you know if it is implemented. Cheers
On Thu, Sep 20, 2018 at 6:07 PM Ron Gierlach notifications@github.com wrote:
@Graeme-Code https://github.com/Graeme-Code, I have not personally used the MiniMe pattern but at a cursory glance of Giveth's repo, it seems you would need to use a version of the MiniMeToken.sol contract modified to implement ERC1404 -- the place to look is function doTransfer() on this contract https://github.com/Giveth/minime/blob/master/contracts/MiniMeToken.sol.
If there is considerable interest in this use-case I would be happy to add an implementation to our examples repo https://github.com/simple-restricted-token/simple-restricted-token.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ethereum/EIPs/issues/1404#issuecomment-423260147, or mute the thread https://github.com/notifications/unsubscribe-auth/AHjHZa18GBJ_sA_N7uD-3jEeQuL4U_jdks5uc8tPgaJpZM4Wktae .
-- I respond faster on Status, use my contact code below to add me: 0x043d3e8477d431c44cdb12f69375726ed3fa83b4409a2848fa8f625c9394f6214ad473cb5314c5c50cb8cc3e4f4ba870afb6364c730a5664f4ad2c523e66ccc431
@veikkoeeva No dumb questions! Will try and address each of these to the best of my ability.
detectTransferRestriction
? Just to make sure as there's a bit of cognitive disonance about ERC-20._isApprovedOrOwner
and zero address logic inside of detectTransferRestriction
. If there is considerable interest in this use-case I would be happy to add an implementation to our examples repo.detectTransferRestriction?
). I might off with this one on the purpose of this (though in that case pointers and clarifications welcome).@rongierlach (or @masonicGIT). Hey, I appreciate you took the time to get back. I'll keep the numbering in the following, but instead of quoting just paraphrase.
By non-fungible securities I mean that some securities are non-fungible, as explained at https://www.repetico.de/card-34407474. In the EU there has been some bonds that are non-fungible due to some extra national serial codes (see here [pdf]), but the desire is to move towards fully fungible ones. I understand it's very desirably to have fungible securities (and even to be trade them globally), but I'm especially looking into green bonds and the problems faced there. Some noted, e.g., at https://www.eco-business.com/news/will-a-lack-of-transparency-hurt-green-bonds/. The Finnish Financial Regulatory Authority, I believe, recently warned about due diligence risks in green bonds. I don't have deep enough knowledge on securities to know if some sort of non-fungibility could solve problems but still keep trading liquid.
This idea has been thought of already, as noted. There's a new standard in the makings that allows batch transfers of fungible and non-fungible tokens, more information at https://github.com/ethereum/EIPs/issues/1155. There's also a new 721x (mentioned at the end of 1155) that builds on 721 directly.
That's true as far as I understand. As I see it, the other way/term looking into sureties is bank guarantees. I don't think these are tradeable assets usually, but can be used to make so, as noted at https://www.bankguaranteefacts.com/trading-bank-guarantees/. Then there are tradeable bank guarantees, though, as noted at https://www.linkedin.com/pulse/fraud-trading-discounted-bank-guarantees-lady-mj-santos.
The reason why I noted these might be dumb, or confused questions, are that I don't have deep knowledge on securities and trading and English isn't my native language (the terminology feels a bit problematic). I see there are plenty of inefficiencies in trading globally and fungibility is very much desired. I'm wondering also if there were a use case, now in the age of blockchain, for non-fungible securities as in with green bonds. I could imagine -- maybe wrongly -- greend bonds issued to construction could be tied to particular buildings are in the power plant building noted in the earlier green bond link. In that sense the bonds might not be fully fungible. Or they might be fully tradeable, but still maintain an unique link to off-chain data (like in ERC-721/ERC-721x/ERC-1155).
While writing this, I noticed Dharma protocol which seems to aim tokenizing debt into securities using ERC-721 (link to Ethereum contracts at https://blog.dharma.io/dharma-bug-bounty-erc721-collateralization-137b2baeca24). In my mind securities and debt securities are around the same issue, but I might be misguided here.
If there is something I could find more information on, I'm happy to do put some effort. I'm equally happy to be noted this is out-of-scope and/or I need to check some sources to increase my understanding otherwise.
Once again, I appreciate the effort to get back with explanations. I for one would appreciate an added sample to the sample repo on non-fungible asset.
I am an eth fan and solidity beginner from China. I think this this standard is very useful. I do some simple implement for this standard. I do not implement the ban function. But it's easy. Every tx can teturn just one restrictionCode .But may have more than one reson for be restricted. Should we solve it? Insert this at transfer and transferFrom function.
uint8 restrictionCode = detectTransferRestriction(_from, _to, _value);
if( restrictionCode != 0 ) {
revert(restrictionCode);
}
There is the ERC1404 contract.
contract ERC1404 is StandardToken , Pausable {
mapping(uint8 => string) restrictionMap;
mapping(address => bool) blackList;
constructor () public {
restrictionMap[1] = "Token is pausing!";
restrictionMap[2] = "sender has been banned!";
restrictionMap[3] = "receiver has been banned!";
}
function detectTransferRestriction (address from, address to, uint256 value) public view returns (uint8){
if (paused == true ) {
return 1;
}
if (blackList[from] == true ) {
return 2;
}
if ( blackList[to] == true ) {
return 3;
}
return 0;
}
function messageForTransferRestriction (uint8 restrictionCode) public view returns (string){
if (bytes(restrictionMap[restrictionCode]).length == 0 ){
return "Restriction code incorrect!";
}
return restrictionMap[restrictionCode];
}
}
@zxlzy At a cursory glance this implementation seems correct. Nice work! 👍
A transaction failing because of more than one reason is a likely possibility. However, modifying the standard to return multiple restriction codes from say a function called detectTransferRestrictions
would be tricky because Solidity does not support returning dynamic arrays. There are workarounds for this, but I feel they would sacrifice the simplicity of the standard.
Hi I noticed #1155 was linked here regarding the batch transfer possibility. I should note that I don't see a problem with someone implementing "AContract is 1155,1404" and in the transferring of tokens simply calling the detectTransferRestriction each time...
However if you did want to do 100 transfers in one batch tx perhaps, the requirement to revert on one non-zero return would mean that for eg. instead of 99 transfers passing and 1 failing, all 100 transfers would fail.
Maybe that is something to consider when developing this standard?
Of course however if the detectTransferRestriction is called for each transaction off chain first, then you could do the above batching without having to enforce the check on chain but I'm not aware of the use cases of this standard enough to say that the detection has to always happen on chain during the transfer to make things transparent and secure.
Perhaps, you would just have to do both off and on checks to "guarantee" a batch would make it through in the majority of cases and still enforce security and transparency.
So offline at least (without regard for usable/nice code):
bool doTheBatchTx = true;
int numberOfTransfers=sizeof(fromArray); // better check your arrays all match and numberOfTransfers > 0
while(numberOfTransfers--) {
if (contract.detectTransferRestriction(fromArray[numberOfTransfers]),toArray[numberOfTransfers],valueArray[numberOfTransfers])) {
doTheBatchTx = false;
break;
}
}
if (doTheBatchTx)
contract.multicastTransferFrom(fromArray,toArray,idArray,valueArray);
else
errorMsg("One of the batch transfers failed the detectTransferRestriction check");
any that might fail the above you could drop from the arrays and at least salvage things (unless you needed to guarantee a set and so dropping the entire set might be desirable).
Really nice and clean. As someone who was involved with the genesis of #1400 (#1410 & #1411), I can really appreciate the simplicity of this. Will monitor and contribute if I can (hard to follow all the conversation as I'm not technically trained).
"The logic of detectTransferRestriction and messageForTransferRestriction are left up to the issuer."
Just to be clear, the detectTransferRestriction doesn't give a third party any knowledge of the full set of transfer restrictions and rules which might apply to a token right? All this standard would do is 1) check if something can be transferred against something offchain and 2) report some sort of error (but not necessarily in any standardized format).
2) report some sort of error (but not necessarily in any standardized format).
I'd suggest use of ERC-1066 and ERC-1444 for this purpose. It's a good thing they've appeared just in time.
Yes, #1066 is used by #1400 / #1411 I'll have to take a look at #1444
@jilaw
The detectTransferRestriction
function is the entry-point for enforcing transfer restriction logic. If said logic is implemented on-chain and the contract source code is public, then it will be obvious to third parties.
However, if a portion or all of this logic depends on a call to an oracle dealing with an off-chain check, this may not be so obvious to a third party -- all this remains up to the issuer.
Standard error codes are not spec'd in #1404 but are a good to be thinking about!
@xlab Error code standardization is an important next step for not just #1404 but the restricted / security token space in general.
Along these lines and in your opinion, should detectTransferRestriction
be modified to return type byte1
rather than uint8
?
Appreciate all the productive discussion around this issue!
Nice proposal! A couple initial thoughts if I may:
Fully agree #1066 is quite suitable for this EIP.
Any particular reason for using byte1/uint8 rather than uint256? Seems artificially restrictive and cost 4x more gas as the EVM just works with uint256 internally
@youfoundron returning dynamic array is supported in newer EVMs. The doc is just catching up to the fact but it's been there since 0.4.22
Do we really need messageForTransferRestriction
? I appreciate that human readable message is useful for the UI layer but seems this should be provided by a web service rather than on-chain function. Do other contracts need to retrieve text messages for interops?
What does the upgrade path look like for this EIP? Regulations or even just developers' self-imposed restrictions change often so the token implementation need to take that into account for its own longevity. I wonder if it'd be a better idea to separate restriction logic from token logic in the reference implementation, below is one way of doing that:
function Token is Erc20, Ownable { IErc1404 restrictor;
function updateRestrictor(address addr) ownerOnly {
restrictor = (IErc1404) addr;
}
modifier notRestricted (address from, address to, uint256 value) {
uint256 restrictionCode = restrictor.detectTransferRestriction(from, to, value);
require(restrictionCode == SUCCESS_CODE, restrictionCode);
_;
}
}
What’s the point of having the standards so specific they are practically designed to work for specific platforms? You might want to have a look at ERC-1462 (https://github.com/AtlantPlatform/BaseSecurityToken/). It’s a really general standard for security tokens, unlike the proprietary methods 1400 and others trying to pump their own projects and hidden agendas. The new standard for security tokens should support as many use-cases as possible, so all teams can start embracing it such as ERC 20.
@jeffishjeff - Excellent feedback, really appreciate your thoughts on this.
We'll explore providing an implementation that leverages #1066 in our examples.
Noted. I agree this should be changed.
This is good to know, thanks for catching me up to speed.
messageForTransferRestriction
is anticipating a best-practice, ie the way the community added details (decimals
, name
, and symbol
) to token contracts. Perhaps it is unnecessary in the event that error codes are standardized, I see your point but I'm on the fence still.
I agree that issuers would do best to put their restriction logic somewhere they can upgrade later and that the reference implementation is fairly contrived. However I feel the reference implementation should be as simple as possible. Will explore providing an implementation that uses detectTransferRestriction
as a proxy for calling the check on a separate contract containing restriction logic that the token owner can swap out the address for -- this is what R-Token does btw.
Really appreciate the thoughtfulness of your feedback. Cheers! 😎
@jeffishjeff
Hey @jeffishjeff - #4 was direct and consistent feedback from technical integrators of the standard. Would be hard to err from this one at the moment.
tagging #1444, an expansion of ERC-1066, to the thread
ik
OK
I think it's terribly bad idea to embrace security tokens:
Enforcing Token Lock-Up Periods (reasonable) Enforcing Passed AML/KYC Checks (this is making ethereum less inclusive / it hurts people from blacklisted countries) Private Real-Estate Investment Trusts ( why you need blockchain for that ) Delaware General Corporations Law Shares ( why you need blockchain for that )
Generally blockchains cannot enforce property rights for things outside of the blockchain context - you may make smart contract that will punish person by slashing their deposit but this is limited ( you cannot enforce below zero that way)
Meanwhile in meatspace actual law is able to enforce with literal force.
Source: https://uncommoncore.co/bitcoin-and-the-promise-of-independent-property-rights/
By adding lots of compliance into Ethereum directly one is hurting the Ethereum values (globally accessible, more free and more trustworthy Internet )
You don't need blockchain to issue equity shares, you can just use regular database. No value is created
"Security Tokens for traditional businesses is like PDF'ing the NYT in the 1990's to put it on the internet. This is a method to put the news on the internet but it is the incorrect approach"
I think it's terribly bad idea to embrace security tokens:
Enforcing Token Lock-Up Periods (reasonable) Enforcing Passed AML/KYC Checks (this is making ethereum less inclusive / it hurts people from blacklisted countries) Private Real-Estate Investment Trusts ( why you need blockchain for that ) Delaware General Corporations Law Shares ( why you need blockchain for that )
Generally blockchains cannot enforce property rights for things outside of the blockchain context - you may make smart contract that will punish person by slashing their deposit but this is limited ( you cannot enforce below zero that way)
Meanwhile in meatspace actual law is able to enforce with literal force.
Source: https://uncommoncore.co/bitcoin-and-the-promise-of-independent-property-rights/
By adding lots of compliance into Ethereum directly one is hurting the Ethereum values (globally accessible, more free and more trustworthy Internet )
You don't need blockchain to issue equity shares, you can just use regular database. No value is created
"Security Tokens for traditional businesses is like PDF'ing the NYT in the 1990's to put it on the internet. This is a method to put the news on the internet but it is the incorrect approach"
Hello - We are simply using the Ethereum blockchain based on demand, its one of the best tested and widely adopted at the moment.
The Ethereum blockchain can always be used completely openly, however when integrated into businesses, they have regulatory obligations. This standard is designed to help them meet their corporate obligations while following their own laws. That in no way impinges certain values onto other users, they are merely additional users on the network.
One of the big benefits of building this on Ethereum is the shared infrastructure. There is the opportunity to build a financial fabric that is available 24/7 and that enables global access to assets in a compliant/automated manner. This may seem like a closed approach, but there is a lot being done to create greater interconnectivity between countries that don't have access to financially mature markets like HK, US, or UK. In a way, it is more powerful that the traditional financial markets are being forced to open up beyond the existing participants.
Either way, greater adoption of Ethereum = more fees for miners :-)
Also - Lawson is an author on the standard.
Sounds right - it seems that the most important part would detectTransferRestriction logic ( where most of the compliance code will be located )
I think it would be useful to specify the content of the revert message when a restriction prevents a transfer
or transferFrom
from running. Otherwise, if a transaction fails and its restrictions are removed immediately after the failure, there'd be no way to know why it failed.
One alternative is to dictate that the revert message should be the one returned by messageForTransferRestriction
with the restrictionCode
that made the transaction fail. Another one is to return the restrictionCode
itself, but as messages are strings and codes uint8
s this may be more complicated to implement in Solidity.
@alcuadrado
We handle the revert message this way in all of our example and reference implementations -- https://github.com/simple-restricted-token/reference-implementation/blob/master/contracts/token/ERC1404/ERC1404ReferenceImpl.sol#L42
Hey @youfoundron, thanks for your quick reply.
I'm aware of that and forgot to mention it in my previous comment. My suggestion is to standardize that behavior, so every compliant implementation does the same.
@alcuadrado Good suggestion. Thanks.
This ERC seems quite elegant to me. I only have a reserve regarding the use of uint8 instead of uint256. Using uint8 is not straightforward as the EVM works with 256bits. In Solidity, we can do an explicit typecast but in Vyper for example there is no such option, just an implicit typecast from uint8 to uint256 which means that messageForTransferRestriction() cannot be called from a smart-contract written in Vyper. I would suggest using uint256 instead of uint8.
@zxlzy At a cursory glance this implementation seems correct. Nice work! A transaction failing because of more than one reason is a likely possibility. However, modifying the standard to return multiple restriction codes from say a function called
detectTransferRestrictions
would be tricky because Solidity does not support returning dynamic arrays. There are workarounds for this, but I feel they would sacrifice the simplicity of the standard.
Why not making the messages codes power of 2 and returning a binary combination?
Eg if Error 1
is 1
, Error 2
is 2
, Error 3
is 4
, Error 4
is 8
, then Error 1
and Error 4
is 9
.
In that sense, the restriction on the return code uint8
might be too small?
The text says:
The standard proposes two functions and an event on top of the ERC-20 standard.
Which event is meant here? It seems not to be referenced.
@ritzdorf great catch, updated accordingly.
ERC1404 support is added to the Ethereum Walet WordPress plugin (https://wordpress.org/plugins/ethereum-wallet/). If transfer is not allowed, corresponding error message would be displayed.
ERC-1404 was just approved for use in a publicly-traded, SEC registered fund. The first time the SEC has approved a token on a public blockchain.
https://www.sec.gov/Archives/edgar/data/1758583/000121465920006145/j76202497.htm
It feels like someone should turn this into an actual standard at some point, rather than just an idea for a standard. 😄
Second sec-registered token on ERC-1404 for INX. This one is a full IPO.
https://etherscan.io/token/0xBBC7f7A6AADAc103769C66CBC69AB720f7F9Eae3#readContract https://www.sec.gov/Archives/edgar/data/1725882/000121390020023202/ea125858-424b1_inxlimited.htm
@rongierlach (or @masonicGIT). Hey, I appreciate you took the time to get back. I'll keep the numbering in the following, but instead of quoting just paraphrase.
- By non-fungible securities I mean that some securities are non-fungible, as explained at https://www.repetico.de/card-34407474. In the EU there has been some bonds that are non-fungible due to some extra national serial codes (see here [pdf]), but the desire is to move towards fully fungible ones. I understand it's very desirably to have fungible securities (and even to be trade them globally), but I'm especially looking into green bonds and the problems faced there. Some noted, e.g., at https://www.eco-business.com/news/will-a-lack-of-transparency-hurt-green-bonds/. The Finnish Financial Regulatory Authority, I believe, recently warned about due diligence risks in green bonds. I don't have deep enough knowledge on securities to know if some sort of non-fungibility could solve problems but still keep trading liquid.
- This idea has been thought of already, as noted. There's a new standard in the makings that allows batch transfers of fungible and non-fungible tokens, more information at ERC: Multi Token Standard #1155. There's also a new 721x (mentioned at the end of 1155) that builds on 721 directly.
- That's true as far as I understand. As I see it, the other way/term looking into sureties is bank guarantees. I don't think these are tradeable assets usually, but can be used to make so, as noted at https://www.bankguaranteefacts.com/trading-bank-guarantees/. Then there are tradeable bank guarantees, though, as noted at https://www.linkedin.com/pulse/fraud-trading-discounted-bank-guarantees-lady-mj-santos.
The reason why I noted these might be dumb, or confused questions, are that I don't have deep knowledge on securities and trading and English isn't my native language (the terminology feels a bit problematic). I see there are plenty of inefficiencies in trading globally and fungibility is very much desired. I'm wondering also if there were a use case, now in the age of blockchain, for non-fungible securities as in with green bonds. I could imagine -- maybe wrongly -- greend bonds issued to construction could be tied to particular buildings are in the power plant building noted in the earlier green bond link. In that sense the bonds might not be fully fungible. Or they might be fully tradeable, but still maintain an unique link to off-chain data (like in ERC-721/ERC-721x/ERC-1155).
While writing this, I noticed Dharma protocol which seems to aim tokenizing debt into securities using ERC-721 (link to Ethereum contracts at https://blog.dharma.io/dharma-bug-bounty-erc721-collateralization-137b2baeca24). In my mind securities and debt securities are around the same issue, but I might be misguided here.
If there is something I could find more information on, I'm happy to do put some effort. I'm equally happy to be noted this is out-of-scope and/or I need to check some sources to increase my understanding otherwise.
Once again, I appreciate the effort to get back with explanations. I for one would appreciate an added sample to the sample repo on non-fungible asset.
Bank Guarantees are not able to be traded, sold or discounted, however they can be monetised if they are a demand bank guarantee and are covered by ICC rules URDG 758
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.
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment.
Simple Restricted Token Standard
Simple Summary
A simple and interoperable standard for issuing tokens with transfer restrictions. The following draws on input from top issuers, law firms, relevant US regulatory bodies, and exchanges.
Abstract
Current ERC token standards have provided the community with a platform on which to develop a decentralized economy that is focused on building Ethereum applications for the real world. As these applications mature and face consumer adoption, they begin to interface with corporate governance requirements as well as regulations. They must not only be able to meet corporate and regulatory requirements but must also be able to integrate with technology platforms underpinning their associated businesses. What follows is a simple and extendable standard that seeks to ease the burden of integration for wallets, exchanges, and issuers.
Motivation
Token issuers need a way to restrict transfers of ERC-20 tokens to be compliant with securities laws and other contractual obligations. Current implementations do not address these requirements.
A few emergent examples:
Furthermore, standards adoption amongst token issuers has the potential to evolve into a dynamic and interoperable landscape of automated compliance.
The following design gives greater freedom / upgradability to token issuers and simultaneously decreases the burden of integration for developers and exchanges.
Additionally, we see fit to provide a pattern by which human-readable messages may be returned when token transfers are reverted. Transparency as to why a token's transfer was reverted is of equal importance to the successful enforcement of the transfer restriction itself.
A widely adopted standard for detecting restrictions and messaging errors within token transfers will highly convenience the exchanges, wallets, and issuers of the future.
Specification
The ERC-20 token provides the following basic features:
The ERC-1404 standard builds on ERC-20's interface, adding two functions:
The logic of
detectTransferRestriction
andmessageForTransferRestriction
are left up to the issuer.The only requirement is that
detectTransferRestriction
must be evaluated inside a token'stransfer
andtransferFrom
methods.If, inside these transfer methods,
detectTransferRestriction
returns a value other than0
, the transaction should be reverted.Rationale
The standard proposes two functions on top of the ERC-20 standard. Let's discuss the rationale for each.
detectTransferRestriction
- This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include, checking if the token recipient is whitelisted, checking if a sender's tokens are frozen in a lock-up period, etc. Because implementation is up to the issuer, this function serves solely to standardize where execution of such logic should be initiated. Additionally, 3rd parties may publicly call this function to check the expected outcome of a transfer. Because this function returns auint8
code rather than a boolean or just reverting, it allows the function caller to know the reason why a transfer might fail and report this to relevant counterparties.messageForTransferRestriction
- This function is effectively an accessor for the "message", a human-readable explanation as to why a transaction is restricted. By standardizing message look-ups, we empower user interface builders to effectively report errors to users.Backwards Compatibility
By design ERC-1404 is fully backwards compatible with ERC-20.
Some examples of how it may be integrated with common types of restricted tokens may be found here.
Test Cases & Implementation
See the reference implementation and tests here.
See some examples of common usage patterns for ERC-1404 here.
Copyright
Copyright and related rights waived via CC0.