@tbergmueller also mentioned they’re working on a use case on Defi. We’re also in talks with some wallet teams about supporting these and other ERCs we have proposed.
To clarify, we do not intend to use the isNonTransferable()
to implement our EIP. But in our protocol, when an NFT is e.g. collateral/security for a loan, transfers are typically blocked for a specific period of time or until some contractual obligations / conditions are met. We saw/see issues with tokens according to our protocol, when people try to sell on market places.
The following has been tried with ERC-5484 , which essentially always throws in _beforeTokenTransfer()
on OpenSea and Rarible (testnet implementations);
If transfer of an ERC721 is blocked temporarily or permanently, the owner can still go ahead and list the token. Often, a owner of a token (which is currently non-transferable) would even pay gas to approve e.g. OpenSea, then list the token for selling. When a buyer comes along and completes signing the purchase, only then would OpenSea says “whoops, I cannot transfer for unknown reasons”.
This is not only annoying, but both, the seller (who pays gas) and often likely also the buyer (who may have sold some other assets to have liquidity (and paid gas+fees+ royalty, … )) spent money on a transaction, that cannot be carried out. Not through the failed transaction, but through other transactions working towards the failing transaction.
To avoid those situations, it would be great if we can propose a standard . Naturally, marketplaces would then need to implement that standard. This is in general likely, as Rarible evidentially already recognizes throwing behavior, as the error says “Soulbound tokens cannot be transfered”.
Towards the question, of how the interface should look like, I can also see a isNonTransferable(from, to, tokenId)
, similar to safeTransfer(from, to, tokenId)
. If tokens cannot be transferred in general, those implementations should simply ignore then the from
and to
and implement logic just on a tokenId-level, essentially achieving the same as isNonTransferable(tokenId)