ERC-4400: ERC-721 Consumer Extension

Just found this EIP.
It is much more elaborate and as you can see it is stagnant and has no activity for a long time.
edit: probably because it is gas expansive.

I keep studying solidity, and I think that there’s no way to use your proposed standard for current ERC721 projects without migrating the contracts, so this is a major drawback.

1 Like

The EIP has been updated with comments received from the community and implementors of the proposal.

@MindfulFroggie I’ve addressed your feedback by enabling approved address + operators to be able to change the consumer. Let me know what you think :slight_smile:

1 Like

Hey there! I was looking over your EIP (I left a review earlier which you resolved), and was wondering if you might want to switch the current setup so that there can be an array of addresses that are consumers instead of just one, since the current setup only allows for one address per tokenId. This doesn’t contradict cases where only one consumer is desired, since the implementing contract can always set a cap on how many addresses can be pushed to the array.

3 Likes

At some point, I was thinking the same thing. Indeed there might be use-cases where you would like to have more than one consumer. I will think about it and maybe even update the proposal with your suggestion. I would like to see how much overhead it would introduce implementation/gas cost wise.

Thank you for the feedback though!

1 Like

The EIP has been updated with reference implementations in LandWorks (already live on mainnet). I have updated the use-cases to include nft staking as-well, since other than no collateral NFT renting, there are other use-cases for this standard which are implemented in the NFT staking mechanism of LandWorks here:

The EIP has been marked as “for review”. Any feedback is greatly appreciated!

Hi, how are you? I was discussing about this EIP these days.

Idea

I think maybe more robust way to face the problem of a standard way of understanding a role that is not the owner could be like roleOf(bytes32 tokenId, bytes4 roleId) returns (address) (or address[] as mentioned above).

Considering

This came up while reading

various metaverses use operator /contributor roles for Land

And also considreing “Mortgage/rental” use case mentioned above.

Result

So this EIP would have a list of standard roles for NFTs (different than owner role) and the specification for each role could reside on newer EIPs linked from here.

This way wallets can then implement standard controls for standard behaviours on standard roles on NFTs.

Use case

Now you could say owner can make use of transfer and approve. With this EIP we could then say role: CONSUMER can utilise the token instances, without necessarily having ownership rights to it (as mentioned in the EIP). Then, other roles like role: TENANT, might add standard functions to query how long the rental is for or a function to extend rental, thus showing these operations in standard way in all wallets and platforms.

1 Like

Hi @ilanolkies
Thanks for the suggestion / feedback. You are right that this proposal introduces new EIP for every role it would require, yes and its not scalable approach. From a first look your proposal sounds good as it can be applied to many roles. The only thing that concerns me is the fact that when a protocol wants to integrate a ERC721 implementing the EIP, they will need to know the exact roleId that has certain permissions and since the roleId can be arbitrary, we will not actually enforce a standard that will help procotols utilise the EIP.

Example → Generic NFT renting protocol wants to support ERC721s that implement the EIP and have a renter role. What would be the roleId that the protocol will be looking for when changing the role / querying the role? Each NFT issuer can define their own ID. In order for this to work, we must define all roles explicitly and their ID. F.e defining that bytes4(keccak("renter")) is the roleId for someone that has permissions to utilise the NFT, but not be able to transfer it.

What do you think would be the mitigation of this issue?

Yes. I really assumed it was clear that roles should have standard ids too

Role for “renter” should have same behavior and same id in any token supporting ERC-4400. Then other roles will have other standard accepted IDs associated with other standard behaviors specified on later EIPs that are accepted as standard by ERC-4400

Similar to what ERC-165 does with interface IDs

Then workflow for having a new standard interface would be

  1. Get the EIP for the standard ERC-4400 extension approved
  2. Propose PR to the list in ERC-4400 adding the interface id and a link to the EIP

This is similar to what ENS does for supporting standard records that can be queried by any wallet. See EIP-137

1 Like

That’s an interesting concept. I will circle that to other NFT discussions in the forum to gather more feedback.

1 Like

Hey Daniel,
I like your proposal. One observation that I had is that this interface requires the consumer to trust the owner/operator as they are no guarantee that the rental agreements will be honored. For example, after a consumer pays the rental fees, the owner or an approver will still be able to change the consumer.
Or I am missing something?

I spent some time looking at NFT rental and to address this trust issue, I thought to delegate the rental agreement logic to a contract IERC721RentalAgreement. This contract controls whether the rent can be started or stopped.
The rent is initiated and stopped from the ERC721 and a callback function to IERC721RentalAgreement can guarantee that the rental terms are fulfilled. For example, IERC721RentalAgreement can enforce that the renter cannot be changed when there is an active rent.
(Also maybe IERC721RentalAgreement contract could handle the role definition?)

Here is the more concrete idea: ERC721 extension to enable rental

1 Like

Do you think it is worth it to discuss the standard way of generically querying extension for roles in another thread? I mean, in a separate thread of how renting should be implemented.

Hi @ArthurBraud
Thank you for the reply and feedback! You are right that the owner is able to change the consumer after he pays for the rent, however, the owner would be actually a smart contract/protocol, meaning that unless there is a bug in the implementation of the protocol, the rents will be honoured.

In order for generic NFT renting to be implemented, we need only the primitive that enables it. It would be easier to have the required “primitive” as standard (aka consumer/delegator etc) and utilise that for the implementation of renting than to propose and finalise a whole renting spec. Maybe I am missing something, but the renting protocol itself can decide on the renting agreements as it would be part of the business logic of the protocol. The only thing it would need is the ability to delegate the utility of the NFT to the renter which is tackled by the consumer role. Actually focusing on the primitive aka “consumer” role, enables other use-cases compared to focusing on rent specification solely. F.e one can implement delegation to 3rd parties or NFT staking.

Let’s keep iterating on the ideas so that we can come up with a solution for this problem. All of us think that it is a pain point and will be an enabler for the NFT community so we are all in the same boat :slight_smile:

I was thinking about the generic role extension that you’ve proposed. To me it seems that it can be applied generally to all types of contracts, f.e not only ERC721s but ERC20 or any contract for that matter. The spec for defining “roles” if described as the ENS reference that you’ve provided can be applied to everything. I am not stating that this is a negative thing. The drawback that I am seeing is that if we define a spec for “Generic Contract Role querying” and have specs for “Consumer Role” or any other type of role, we end up with a spec that overlaps (is a subset) with the existing ERC165 spec. Both of them address the same need: providing information on what is supported by the target contract.

Going with a concrete example. Let’s say that one way is to go with the same existing proposals:

  • ERC165 support + Role-specific extension

and the other way is:

  • “Generic Role Querying” + “Role-specific extension”

Wouldn’t it be the same whether we use ERC165 to figure out whether something is supported or not vs using the “generic role querying” to figure that out?

Maybe I am missing something. Can you please provide your thoughts on my concerns?

Hello Daniel @Daniel-K-Ivanov

We are trying to use this erc4400 standard in our dapp. Would love you have your guidance. Would you be available for a call?

Cheers,
Anir

1 Like

It is not just for querying what interfaces the contract support. It is for accessing the given role via its role ID. Maybe I am being to generic but this will enable easier integration from wallets and dapps if need to support different role type

Hello,

I was wondering why the consumer should be reset to address(0) when there is a transfer.
Wouldn’t it make more sense to default it to the owner’s address?
I have in mind projects who refer to the consumer address to give out benefits, like airdrops or whatever. I guess it would make more sense for the owner to be the default consumer when he/she isn’t renting out the token.

Cheers,

Aloys

Hello @MissieBish
The proposed design clears the consumer address similar to why approved addresses for a given tokenId are cleared on transfer. We wouldn’t want to keep the same consumer on transfer since it is an attack/exploit vector to the new owner of the tokenId.

Do you think that ERC4400 must specify the address to which consumer must be updated on transfer? I am citing this:

On every transfer, the consumer MUST be changed to the zero address the same way approve address is changed.

I think that if we enforce the default address to which we must change the consumer on transfer we will be again enforcing a rule that might not fit every use case. F.e some projects may want to provide the utility of the NFT to both the owner and the consumer, but projects may prefer NOT to provide the utility of the NFT to the owner but only the consumer. That being said, I think that we can update the spec in the following way:

On every transfer, the current consumer MUST be changed to a default address. It is RECOMMENDED for implementors to use `address(0)` as that default address. 

Hello Daniel,

Thank you for your reply.

To answer your question, I do not think that the updated consumer address should be specified on transfer. It could have unwanted ramifications (for example, a borrowed nft could be returned to the original owner with a modified consumer address).

I think your proposed modification to the spec is very appropriate, it does give more flexibility to ERC4400 implementations to fit their intended needs more closely (I have a real life example in mind: I rent a flat, my landlord sells the flat, I’m still the renter of that flat despite the new owner. A land register ERC4400 can deal with that under your proposed modified spec).

All the best,

Aloys

This idea has been on my mind as well recently, and looking through various threads on this forum it seems others have too, and it seems this one is most active and willing to be updated to fit the needs of various use-cases.

The need to have another “role” (or set of roles) beyond “owner” and “approved” (the labels used in the ERC721 standard) I agree with the general concept of. I think updating this EIP to have a more generic form of “roles” that a contract can use, plus have the option to extend with custom roles is a good direction to go in.

EIP634 is the (currently draft) standard for how the ENS specifies text metadata on their tokens, in which the standard has a few Global keys that it defines, plus lays out a structure for custom keys. That standard only allows for one value of each text key, but for this extension on the ERC721 standard, because the ERC721 standard allows for both “approved” (for one token) and “approved for all”, it might be a good idea to keep that concept of every “role” could be assigned to one address, or one address marked as having that role for all tokens.

Alternatively, the roles could be identified by bytes32 values that are hashes of known structures. That’s a style that’s done in the OpenZeppelin AccessControl template contract, and used as typeHash identifiers in EIP712. With that idea, a “renter” role would be identified not as "renter", but as keccak256("renter").

Additionally, this EIP is structured to be an “extension” meaning that new ERC721 contracts deployed after this standard could choose to implement it. Existing ERC721 contracts could use the new extension by creating a new contract and having users convert (“wrap” or “upgrade”) to the new contract, and then they could have “in-place”/“non-custodial” staking/renting, but the current ecosystem of NFT marketplaces would then treat that new contract as a new “collection” and not carry the previous collection’s history forward (and makes user experience harder, as users need to then be given ways to be assured the new collection is legitimate and not a scam/copycat collection). For contracts that already exist, or platform infrastructures that want to provide generic staking/rental options for many different tokens, or for multisig wallets that hold ERC721 tokens, extending this EIP to have consumerOf(address tokenCollection, uint256 tokenId) (representing an inquiry like “hey smart contract, you’re marked as having some role for token #100 from collection ABC. For your logic, what (if any) other address has rights to trigger you to do something on behalf of token #100 from collection ABC?”) would be helpful. This would allow chaining together role requests, to find a final EOA that represents the human behind the role, making wallet and portfolio UIs able to better enumerate all tokens a user has some rights/roles to.

For completeness (and to tag them as linked from here), my research searching around for similar proposals yielded these other EIPs that have attempted to do similar things:

  • EIP900 - Simple Staking Interface: Created early 2018 and is now marked Stagnant in the EIPs repository.
  • EIP1132 - Time-locking tokens within a contract: Created in late 2018 and is merged into the EIPs repository as a Draft.
  • EIP4353 - Viewing Staked Tokens in NFT: Drafted late 2021, had a merge request to the EIPs repository that got closed without merging in. Discussion comments on this one were that it might be too specific to a single application use.
  • ERC4902 - Decentralized Autonomous Access: An attempt to quantify different holding patterns as different levels of “trust”. Drafted early 2022 and closed out without merging.

And other discussion threads here on relevant topics:

EIP-4400: ERC-721 Consumable Extension with @Daniel-K-Ivanov