Minimalistic transferable interface

Just brainstorming this a little bit further.
What do you think about instead of having every contract implement all these new functionality and add that little piece of data to its own state, to just have a central contract on each chain to manage all that sort of data (on-chain metadata, so to speak) in one place. Contract as a service sort of thing that would hold arbitrary information for all other contracts on the chain. :thought_balloon:

That could have a huge DRY impact

However, we still need to consider that the current owner or the recipient can influence the transferability of an NFT. Above, @stoicdev0 was pointing out
a use case where the token is locked or not depending on the address having another token

No special need for this beyond not having events since they don’t make sense in this scenario. You can implement whatever logic you want to return the result, that includes calling other contracts.

I don’t like this depending on recipient or anything besides the tokenId. It’s too specific IMO for a minimalistic interface.

I prefer the simplest solution too, but in your specific case, if a token can be transferred depending on the address having another token, I would expect that a similar rule can be applied also to the receiver. So, if you do not specify the receiver, how can you establish if that token is transferable or not?

The tradeoff is between the simplest possible interface and a bit more complex interface that covers all the possible scenarios. If we go with the first case, maybe a partial implementation of ERC5192 is enough.

That is an interesting approach, but how can that central contract know all the rules applicable to the NFT in different games, defi, etc.? It would require that the game, somehow, tells the registry how to manage the single case. It seems not feasible. Much easier that everyone manages its own stuff and there is a simple way to tell others what is going on.

Yeah, well, the contract has to explicitly declare that either way. And either way, we’d need to add some code to write that data. It would make it simpler to read, find and index. Well, I guess you could call it an index contract.

It just seems that looking at the crypto space as a community of microservices, and especially when limited to 24k, it might make more sense to have a central service that handles all similar things everyone needs. Like arbitrary identifying data, such as this, contractURI, etc’

Maybe some kind of an arbitrary data protocol for taking out all of these birds and future birds with one stone.
It would also maybe offer some relief to the spaghetti and lack of backward compatibility issue that each of these standard changes introduces.

… just a thought :blush:

I recently submitted the “Untransferability Indicator” EIP. Currently it is for EIP-1155 tokens, but eventually I want to implement untransferability for any token specification.

I support your idea if it can be applied to ERC-20 token.

IMO, any tokens have transferability by default. Untransferable tokens is the specific case of them. So, I think it’s better “Untransferability Indicator” or “Untransferability Interface” than “Transferable Interface”

1 Like

That is a big problem. For Everdragons2 we are building a contract-as-a-service system to generate subordinate contracts and I am very sensitive to that issue. The problem is that a service like that, to be reliable, should index the entire blockchain. Some kind of Google for EVM. It would be fantastic, if we had something like that. I am sure that can be done, but composability, for now, is what we have and we take advantage of it.

I think you are right. Let’s go back to the initial formulation. A minimalistic case where it just says if a tokenId is transferable or not. In the end, that is needed by external entities, like marketplaces, the internal marketplace does not need to call the view because it knows what to do.

I think the discussion has been very productive.

A question for the moderators
In general, is it better to update the initial post or is it better to link an updated document? I may create a simple repo for it.

1 Like

Since an ERC20 is fungible, it can be either transferable or not transferable, if this interface would be applied.

If that is not the case, for example a token can be vested and there can be cases where the owner cannot transfer it or the recipient cannot receive it, this interface doesn’t work.
We need a more complex function, like the one I proposed a few comments above:

function isTransferable(
  address from, 
  address to, 
  uint tokenIdOrAmount) 
external view returns(bool);

This would support also ERC20 and any other asset that is transferable between two addresses. The problem here is if to keep the interface minimalistic and simple, or make it capable of managing any possible scenario. It looks like the tendency is towards the first case.

Cool. Thanks for the feedback. That’s what I use that in my protocols, I’ll try to push it forwards a bit.

as for a simple solution for finding out if a token is transferable, I think it should be enough for us all to agree on an error message (like ‘Token-Not-transferable’) in case it’s soulbound. Then if a contract doesn’t have a transfer function, or returns such an error, we can deduce it’s soulbound. Seems simpler and more lightweight.

Honestly, NFT standards only leave you about 18kb to work with. I would have a hard time supporting any additions to them. It seems to make much more sense to just remove the transfer functions. Wouldn’t that serve the same purpose with less code?

If the token is non-transferable, despite if we agree or not on a specific error, that transaction will revert consuming at least 40000 gas. It is better to allow a marketplace to check that before calling it. If not, we don’t really solve the issue.

From my experience if transactions are going to fail metamask will tell you beforehand. You can also simulate the transaction before sending it to the chain to check if it might fail and that’s free.

Maybe you can expand more about the specific situation where a revert incur a cost?

1 Like

I think that that is exactly what MetaMask does. But it is a work around in absence of a clear solution that is valid for everyone and everyone can verify. Anyway, I got your point and it is valid.

Gotcha. Thanks, and good luck! :pray:

1 Like

I am working on a new project where, for security reasons, the tokens are transferable only by the owner and cannot be approved without the owner make the contract approvable.

So, I am thinking that it could make sense to have a just-a-bit-less-minimalistic interface like

interface IERCxxx {
  function isTransferable(uint tokenId) external view returns (bool);
  function isApprovable(uint tokenId) external view returns (bool);
}

Of course, we may suggest a new interface only for the approvability, but any token who would implement both, would spend more gas because it has to check the two interfaceId.

What do you think?

I’m strongly against it, it defeats the purpose of minimalism. I have created 4-5 use cases using the minimal version and in non of them there was approvable in any way.

I would do a different EIP for that. It’s true implementers of both will spend a bit more gas on the check (unless you use a mapping, in which case the extra gas is only paid once, and by the issuer). The alternative is to force all implementers of only soulbound to have an extra unused method, it’s a clear choice IMO.

I’m feeling conflicted. While I agree with the principle, I’m currently working on several projects related to escrows and secure vaults, and in none of them can I use the IERC6454 function. By default, the tokens in these projects are non-tradeable for security reasons, which means they can’t be approved. The scenario where you only need to check the transferability of a token and don’t have to worry about its approvability seems rare.

A token that is non-transferable can either be approved for future transferability or cannot be approved at all. As an exchange, it’s challenging to decide whether to try to approve the spending or not. The easy solution is to have a second interface that checks only for approvability, but I don’t find it exciting.
I believe that whoever wrote the ERC721 proposal overlooked these two views. They should have been there from the beginning.

Anyway, I have implemented an IERC721Approvable interface inside the protector-protected-protocol. I wonder if it would make sense to make a standard proposal of it.

I think I will start a new discussion about it.

In eip6147, by querying the guard information, it is already possible to know whether the token can be transferred.

1 Like

Nice proposal. But it would make no sense for someone to implement it without implementing the entire protocol. Here (as in ERC6454) we are talking about the minimal effort necessary to let an exchange know it the token is transferable or not.