I just want to clarify what I was proposing because I get the sense we’re talking about different things.
When I say “optional”, what I mean is that an implementer must mark their implementation as either immutableormutable. If they mark it as immutable, then their implementation would be compliant with your original proposal, and therefore provide all of the guarantees and benefits of immutability that you have mentioned. Other implementers could chose to mark their implementation as mutable, allowing them to use this standard for use-cases that rely on mutability.
Or, put differently, my proposed changes wouldn’t compromise immutability in any way that I’m aware of.
I’m not aware of an off-chain mechanism that currently exists for smart contract interface detection but, if it does, it wouldn’t be mutually exclusive with ERC-165, and it also wouldn’t solve the problem of on-chain interface detection.
I’m not sure how this relates to the question of requiring ERC-165 or optional immutability? The only way to truly verify compliance would be to perform an audit of the implementation, and this standard can’t solve that.
Ah, I see what you are saying now. I think you should just have two standards in this case. I don’t see any advantage in having a single standard with two mutually exclusive modes vs two separate standards. Once EIP-5114 is final, someone could make a copy of it, remove the immutability/addressability comments, and push that quickly through to final. This makes it more clear when a user says “I have an EIP-5114 badge” what exactly that means, rather than requiring they say “I have an [im]mutable EIP-5114 badge”.
It doesn’t, it was related to the immutability discussion.
https://tokenlists.org/ You are correct it isn’t mutually exclusive, but if you are using something that then 165 is unnecessary.
You are correct, tokenlists don’t solve the problem of on-chain detection. While it won’t likely change my position on this, I’m curious what is the use case for interface detection on-chain?
I think the key to my argument regarding EIP-165 is that standards are composable, so one can create a token that is EIP-165 & EIP-5114. Similarly, one can build an application that only works with tokens that are both EIP-165 & EIP-5114 and this is fine. Standards should be as small as possible to define something useful, and in the case of 5114 that means leaving out a requirement on 165. I would be totally fine with apps being built that only support 165 + 5114 tokens and refusing to support 5114 tokens that don’t implement 165, but this doesn’t mean we need to have an explicit standard for that composition.
I think we could go back and forth on these points indefinitely, so I’m going to respectfully disagree and duck out of this discussion here! I’d be interested to hear some viewpoints from other people.
For anyone interested in arguing that 165 should be required in this EIP, the argument I would like to see is one that expresses what the difference is between these two apps:
“Works with badges that implement EIP-5114” – where EIP-5114 has a hard dependency on EIP-165
“Works with badges that implement EIP-5114 & EIP-165” – where EIP-5114 doesn’t depend on EIP-165
Similarly, for anyone interested in arguing that this EIP should support both immutable and mutable badges, I would like to see the argument in how these two apps differ:
“Works with badges that implement EIP-5114 & EIP-X” – where EIP-X is a mutable version of EIP-5114
“Works with badges that implement EIP-5114” – where EIP-5114 has a flag for mutability
Dear MicahZoltu,
I am a contract developer at Sharkz Entertainment, we recently launched a public “Soulbound” expirement for the concept, your EIP inspired us to create the whole expirement and really created the backbone of our project, our team created an implementation contract for EIP5114.
I believe we successfully retained your original concept of immutalbe “badge” design, our ERC5114 contract is binding “Soul Badge” to a “Soul” (ERC4973), permanently at mint time!
Please review our contracts when you got the time, and please have fun to play around with it, thanks!
Glad to see someone implementing this. I left an issue on the repository about the burn function, which makes it EIP-5114 incompatible. At a glance it otherwise looks reasonable (definitely didn’t do a thorough review/audit though).
We are now updating our implementation to remove all burning functions relating to EIP-5114, also, we are updating the contract following the last update to the EIP interface, adding “metadataFormat” and we will just return the schema string from EIP-712 - ERC721 Metadata JSON Schema.
However, I find it is quite inconvenient on “function collectionUri() external pure…”, for a function to be marked as “pure”, the uri will be forced to “hardcode” in the function, making it hard to design an easy-to-use abstract/library contract that other final contracts can extend from, I think immutable requirement can be implemented in many ways, it need not to be forcing the function to be “pure”.
If EIP-5114 mandates EIP-165, then a compliant viewer application can implement only autodetection of badges using supportsInterface and a log subscription.
If EIP-5114 doesn’t mandate EIP-165, then a compliant viewer application needs to have EIP-165 autodetection, plus some other method (maybe logs, and try calling a function unique to EIP-5114?)
One can simply write a 5114 && 165 compliant viewer application. There is no need to have one standard depend on another for an application to depend on both. In fact, at the moment I would advocate strongly that all tokens implement both 5114 && 165 if they want maximum compatibility, and all viewers only support 5114 && 165 tokens and simply don’t support 5114 tokens that aren’t 165 compliant if they need the ability to introspect (many tools don’t need introspection).
What I want to avoid is having this standard no longer be applicable in the future when some new introspection mechanism becomes available that people switch to. I would rather applications just become 5114 && (12345 || 165) or 5114 && 12345 compliant than have to create a whole new standard that is 90% a copy of 5114.
To frame this differently, if someone created a new standard EIP-6789 which was just EIP-5114 + EIP-165, and then everyone created EIP-6789 tokens I think that would be functionally the same as if I add a dependency on 165 directly to EIP-5114. If we accept that assertion, then on the principal of smallest possible standard that can exist on its own, I think 5114 without a hard dependency on 165 is the correct path, and then create a separate standard for the combination.
Taking it a step further, this hypothetical 6789 standard feels like a Good Idea, but not actually necessary as a Standard since anyone can simply choose to implement 5114 + 165 together because that is a Good Idea for maximizing interoperability, but it doesn’t actually need to be formalized because 5114 and 165 both already exist.
I honestly find it unrealistic that EIP-165 is going to be replaced. A majority of existing EIP-20 and EIP-721 tokens implement it and have no pattern to upgrade, so what besides technical vision makes you speculate that EIP-165 may not be useful anymore in the future?
As part of our process to encourage peer review, we assign a volunteer peer reviewer to read through your proposal and post any feedback here. Your peer reviewer is @rianhughes! Please note that this review is NOT required to move your EIP through the process. When you—the authors—feel ready, just open a pull request.
If any of this EIP’s authors would like to participate in the volunteer peer review process, shoot me a message!
@rianhughes please take a look through EIP-5114 and comment here with any feedback or questions. Thanks!
I think that an interface should never request to extend ERC165.
Despite the philosophical reasons (on which I agree with you), in most cases, an interface XXX is ERC165 {}
breaks the linearization of the smart contract that implements XXX.
However, I find it helpful to explicitly express the interfaceId in case someone wants to check it using supportsInterface(bytes4).
Just a heads up, I put up a pull request to hopefully make the terminology more consistent (badge vs. token.)
the metadata returned by this is merged with the metadata return by badgeUri(uint256)
data from tokenUri takes precedence over data returned by this method
data from this takes precedence over data returned by collectionUri
These three taken together seem to imply that to retrieve the metadata for any badge, an interested application would have to call collectionUri then tokenUri and then perform some unspecified merge operation to calculate the final result. Is that correct? If so, it might be worth adding something about the merge algorithm being determined by the result of metadataFormat to the rationale.
My intent was that merging was part of the “to be determined by future spec” per the comment in the rationale:
The format of the data pointed to by collectionUri() and tokenUri(uint256) is intentionally left out of this standard in favor of separate standards that can be iterated on in the future. The immutability constraints are the only thing defined by this to ensure that the spirit of this token is maintained, regardless of the specifics of the data format. The metadataFormat function can be used to inform a caller what type/format/version of data they should expect at the URIs, so the caller can parse the data directly without first having to deduce its format via inspection.
This feels like metadata about the EIP, but not part of the standard itself. In particular, I’m imagining a future where there are competing standards with EIP-165 that have different formats and the EIP would only include the bytes4 for EIP-165 even if no one uses it anymore. I wonder if there is some way we could generalize this for ERCs? IIUC, the bytes4 can be calculated from the contract’s interface. Perhaps someone can just create a simple JS tool hosted on IPFS that lets you paste in a Solidity interface and will spit out it’s bytes4?
One goal of an interface like this should be avoiding that exchanges start useless transactions trying to approve or transfer an asset. The easy way for an exchange is to verify the interfaceId. In that case they would probably just check the bytes4 instead of type(Interface).interfaceId. But I am fine with not indicating it. On the other end, surprisingly, considering your opinion about it, in the EIP doc it specifies that this ERC requires the implementation of ERC165, which is confusing.
Implementers of this standard SHOULD also depend on a standard for interface detection so callers can easily find out if a given contract implements this interface.