From 6b8e5e0be123d0c140ec2881f0cd8099a96fe5d2 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Thu, 26 Oct 2023 12:29:02 -0700 Subject: [PATCH 01/13] Readding ERC-7531 --- ERCS/erc-7531.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 ERCS/erc-7531.md diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md new file mode 100644 index 0000000000..ebbc65c15d --- /dev/null +++ b/ERCS/erc-7531.md @@ -0,0 +1,73 @@ +--- +eip: 7531 +title: Getting Staked ERC-721 Ownership Recognition +description: Recognizing NFT ownership when staked into other contracts. +author: Francesco Sullo (@sullof) +discussions-to: https://ethereum-magicians.org/t/eip-7531-resolving-staked-erc-721-ownership-recognition/15967 +status: Draft +type: Standards Track +category: ERC +created: 2023-10-01 +requires: 165, 721 +--- + +## Abstract + +The ownership of [ERC-721](./eip-721.md) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they've been staked. + +## Motivation + +Recent solutions involve retaining NFT ownership while "locking" the token when staked. However, this requires the NFT contract to implement lockable functionality. Many early vintage NFTs like CryptoPunks or Bored Ape Yacht Club were not originally designed as lockable. + +When these non-lockable NFTs are staked, ownership transfers fully to the staking pool contract. This prevents the original owner from accessing valuable privileges and benefits associated with their NFTs. + +For example: + +A BAYC holder would lose access to the BAYC Yacht Club and member events when staked. +A CryptoPunks holder may miss out on special airdrops or displays only available to verified owners. +Owners of other early NFTs like EtherRocks would lose the social status of provable ownership when staked. +By maintaining a record of the original owner, the proposed interface allows these original perks to remain accessible even when the NFT is staked elsewhere. This compatibility is critical for vintage NFT projects lacking native locking mechanisms. + +The interface provides a simple, elegant way to extend staking compatibility to legacy NFTs without affecting their core functionality or benefits of ownership. + +## Specification + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174. + +The interface is defined as follows: + +```solidity +interface IERC7531 { + // It MUST revert if the token is not staked + function holderOfRightsFor( + address tokenAddress, + uint256 tokenId + ) external view returns (address); +} +``` + +The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./eip-721.md) from staking another [ERC-721](./eip-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./eip-721.md) contract has only one `ownerOf` function. + +Also, the name `holderOfRightsFor` is more descriptive of the function's purpose and is also more generic, as it could be used for other rights, not only ownership. For example, a staking pool may allow Bob to stake a token that can be later unstaked by Alice. In this case, the function should most likely return Alice's address. + +## Rationale + +This approach provides a workaround for the challenges posed by non-lockable NFTs. By maintaining a record of the original owner and exposing this through the `holderOfRightsFor` method, we ensure that staking does not hinder the utility or privileges tied to certain NFTs. + +## Backwards Compatibility + +This standard is fully backwards compatible with existing [ERC-721](./eip-721.md) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](./eip-721.md) standard but acts as an enhancement for staking pools. + +## Security Considerations + +A potential risk is that a staking pool could improperly assign ownership to a different wallet through this interface. This would allow that wallet to potentially access privileges associated with the NFT. + +However, this is a much lower risk than transferring full legal ownership of the NFT to the staking pool initially. The interface only enables recognizing the staker, not replacing the actual owner on-chain. + +Overall, improper use of this interface poses some risk of inaccurate ownership records. But this is an inherent issue with any staking arrangement, and is reduced by the owner retaining custody rather than transferring ownership. + +As with any privilege granting NFT, consumers should evaluate staking providers carefully for signs of mismanagement or fraud. The interface itself does not enable any new manipulation capabilities, but prudent caution is always warranted. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From 0de64d71b8d8a731d58c797afd948f08a35c989f Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Thu, 26 Oct 2023 12:31:17 -0700 Subject: [PATCH 02/13] Fix eip- erc- --- ERCS/erc-7531.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index ebbc65c15d..a4ec91f490 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -13,7 +13,7 @@ requires: 165, 721 ## Abstract -The ownership of [ERC-721](./eip-721.md) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they've been staked. +The ownership of [ERC-721](./erc-721.md) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they've been staked. ## Motivation @@ -46,7 +46,7 @@ interface IERC7531 { } ``` -The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./eip-721.md) from staking another [ERC-721](./eip-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./eip-721.md) contract has only one `ownerOf` function. +The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./erc-721.md) from staking another [ERC-721](./erc-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./erc-721.md) contract has only one `ownerOf` function. Also, the name `holderOfRightsFor` is more descriptive of the function's purpose and is also more generic, as it could be used for other rights, not only ownership. For example, a staking pool may allow Bob to stake a token that can be later unstaked by Alice. In this case, the function should most likely return Alice's address. @@ -56,7 +56,7 @@ This approach provides a workaround for the challenges posed by non-lockable NFT ## Backwards Compatibility -This standard is fully backwards compatible with existing [ERC-721](./eip-721.md) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](./eip-721.md) standard but acts as an enhancement for staking pools. +This standard is fully backwards compatible with existing [ERC-721](./erc-721.md) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](./erc-721.md) standard but acts as an enhancement for staking pools. ## Security Considerations From 2bd1cbaaf632cb7ac8286add349dd02bee48fbcb Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 07:10:56 -0800 Subject: [PATCH 03/13] Try to force reload --- ERCS/erc-7531.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index a4ec91f490..daba6a9e4e 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -23,7 +23,7 @@ When these non-lockable NFTs are staked, ownership transfers fully to the stakin For example: -A BAYC holder would lose access to the BAYC Yacht Club and member events when staked. +A BAYC NFT holder would lose access to the BAYC Yacht Club and member events when staked. A CryptoPunks holder may miss out on special airdrops or displays only available to verified owners. Owners of other early NFTs like EtherRocks would lose the social status of provable ownership when staked. By maintaining a record of the original owner, the proposed interface allows these original perks to remain accessible even when the NFT is staked elsewhere. This compatibility is critical for vintage NFT projects lacking native locking mechanisms. From 7cefa480b88dc029b47db1ce3c2291715d703479 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 07:27:48 -0800 Subject: [PATCH 04/13] Move from ./erc- to ./epi --- ERCS/erc-7531.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index daba6a9e4e..0424fa0b60 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -13,7 +13,7 @@ requires: 165, 721 ## Abstract -The ownership of [ERC-721](./erc-721.md) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they've been staked. +The ownership of [ERC-721](./eip-721.md) tokens when staked in a pool presents challenges, particularly when it involves older, non-lockable NFTs like, for example, Crypto Punks or Bored Ape Yacht Club (BAYC) tokens. This proposal introduces an interface to address these challenges by allowing staked NFTs to be recognized by their original owners, even after they've been staked. ## Motivation @@ -46,7 +46,7 @@ interface IERC7531 { } ``` -The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./erc-721.md) from staking another [ERC-721](./erc-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./erc-721.md) contract has only one `ownerOf` function. +The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./eip-721.md) from staking another [ERC-721](./eip-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./eip-721.md) contract has only one `ownerOf` function. Also, the name `holderOfRightsFor` is more descriptive of the function's purpose and is also more generic, as it could be used for other rights, not only ownership. For example, a staking pool may allow Bob to stake a token that can be later unstaked by Alice. In this case, the function should most likely return Alice's address. @@ -56,7 +56,7 @@ This approach provides a workaround for the challenges posed by non-lockable NFT ## Backwards Compatibility -This standard is fully backwards compatible with existing [ERC-721](./erc-721.md) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](./erc-721.md) standard but acts as an enhancement for staking pools. +This standard is fully backwards compatible with existing [ERC-721](./eip-721.md) contracts. It can seamlessly integrate with existing upgradeable staking pools, provided they choose to adopt it. It does not require changes to the [ERC-721](./eip-721.md) standard but acts as an enhancement for staking pools. ## Security Considerations From c917567648d34b10157ad5540c8981a2c5fdbfac Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 08:37:33 -0800 Subject: [PATCH 05/13] Adding specifications about the event --- ERCS/erc-7531.md | 60 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index 0424fa0b60..e00003d0aa 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -38,6 +38,16 @@ The interface is defined as follows: ```solidity interface IERC7531 { + // This event MUST be emitted when the token's technical owner (i.e., the contract holding the token) + // differs from the actual owner (i.e., the entity with rights to the token). This distinction is + // particularly relevant for staked tokens, where the technical owner is typically the staking contract. + // The event MUST be emitted in the same block as the Transfer event emitted by the ERC-721 contract or in + // any following block. In any case, any new Transfer event involving the same token invalidates the + // previous HolderOfRightsFor event. + // Since any smart contract could emit a fake HolderOfRightsFor event, entities listening to the event, + // MUST check that the contract emitting the event is the current owner of the token. + event HolderOfRightsFor(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); + // It MUST revert if the token is not staked function holderOfRightsFor( address tokenAddress, @@ -46,13 +56,43 @@ interface IERC7531 { } ``` -The function name could have been simply `ownerOf` but nothing stops a standard [ERC-721](./eip-721.md) from staking another [ERC-721](./eip-721.md), and in that case the function's name would conflict with the standard `ownerOf` function, forcing the caller of the second to specify the signature to distinguish between the two functions. That may break existing apps that expect that an [ERC-721](./eip-721.md) contract has only one `ownerOf` function. +The `HolderOfRightsFor` event is crucial for accurately identifying the actual owner of a staked token. In scenarios where a token is staked in a contract, the [ERC-721](./eip-721.md) Transfer event would incorrectly assign ownership to the staking contract itself. The `HolderOfRightsFor` event addresses this discrepancy by explicitly signaling the real owner of the token rights. -Also, the name `holderOfRightsFor` is more descriptive of the function's purpose and is also more generic, as it could be used for other rights, not only ownership. For example, a staking pool may allow Bob to stake a token that can be later unstaked by Alice. In this case, the function should most likely return Alice's address. +### Timing of Event Emission: + +The `HolderOfRightsFor` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of staked tokens. + +### Invalidation of Previous HolderOfRightsFor Events: + +To maintain compatibility with the broader ecosystem and optimize for gas efficiency, any new `Transfer` event involving the same token invalidates the previous `HolderOfRightsFor` event. This approach ensures that the most recent `Transfer` event reliably reflects the current ownership status, negating the need for additional events upon unstaking. + +### Important Consideration Regarding Event Authenticity: + +Given that any smart contract has the ability to emit a `HolderOfRightsFor` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `HolderOfRightsFor` event is indeed the current holder (i.e., the technical owner) of the token in question. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. ## Rationale -This approach provides a workaround for the challenges posed by non-lockable NFTs. By maintaining a record of the original owner and exposing this through the `holderOfRightsFor` method, we ensure that staking does not hinder the utility or privileges tied to certain NFTs. +### Addressing Non-Lockable NFT Challenges: + +Non-lockable NFTs present a unique challenge in decentralized ecosystems, especially in scenarios involving staking or delegating usage rights. The standard ERC-721 ownerOf function returns the current owner of the NFT, which, in the case of staking, would be the staking pool contract. This transfer of ownership to the staking pool, even if temporary, can disrupt the utility or privileges tied to the NFT, such as participation in governance, access to exclusive content, or utility within a specific ecosystem. + +### The holderOfRightsFor Method: + +The `holderOfRightsFor` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is staked in a pool. + +### Technical Advantages: + +1. Preservation of Utility: This approach allows NFT owners to leverage their assets in staking pools or other smart contracts without losing access to the benefits associated with the NFT. This is particularly important for NFTs that confer ongoing benefits or rights. + +2. Enhanced Flexibility: The method offers greater flexibility for NFT owners, allowing them to participate in staking and other DeFi activities without relinquishing the intrinsic benefits of their NFTs. + +3. Compatibility and Interoperability: By introducing a new method instead of altering the existing ownerOf function, this EIP ensures backward compatibility with existing ERC-721 contracts. This is crucial for maintaining interoperability across various platforms and applications in the NFT space. + +4. Event-Driven Updates: The `HolderOfRightsFor` event facilitates real-time tracking of the rights-holder of an NFT. This is particularly useful for third-party platforms and services that rely on up-to-date ownership information to provide services or privileges. + +### Addressing Potential Misuse: + +While this approach introduces a layer of complexity, it also comes with the need for diligent implementation to prevent misuse, such as the wrongful assignment of rights. This EIP outlines security considerations and best practices to mitigate such risks. ## Backwards Compatibility @@ -60,13 +100,19 @@ This standard is fully backwards compatible with existing [ERC-721](./eip-721.md ## Security Considerations -A potential risk is that a staking pool could improperly assign ownership to a different wallet through this interface. This would allow that wallet to potentially access privileges associated with the NFT. +A potential risk with this interface is the improper assignment of ownership by a staking pool to a different wallet. This could allow that wallet to access privileges associated with the NFT, which might not be intended by the true owner. However, it is important to note that this risk is lower than transferring full legal ownership of the NFT to the staking pool, as the interface only enables recognizing the staker, not replacing the actual owner on-chain. + +### Event Authenticity: + +There is a concern regarding the potential emission of fake `HolderOfRightsFor` events. Since any contract can emit such an event, there's a risk of misinformation or misrepresentation of ownership. It is crucial for entities listening to the `HolderOfRightsFor` event to verify that the emitting contract is indeed the current owner of the token. This validation is essential to ensure the accuracy of ownership information and to mitigate the risks associated with deceptive event emissions. + +### Reducing the Risk of Inaccurate Ownership Records: -However, this is a much lower risk than transferring full legal ownership of the NFT to the staking pool initially. The interface only enables recognizing the staker, not replacing the actual owner on-chain. +While improper use of this interface poses some risk of inaccurate ownership records, this is an inherent issue with any staking arrangement. The risk is somewhat mitigated by the fact that the owner retains custody rather than transferring ownership. -Overall, improper use of this interface poses some risk of inaccurate ownership records. But this is an inherent issue with any staking arrangement, and is reduced by the owner retaining custody rather than transferring ownership. +### Due Diligence: -As with any privilege granting NFT, consumers should evaluate staking providers carefully for signs of mismanagement or fraud. The interface itself does not enable any new manipulation capabilities, but prudent caution is always warranted. +Consumers of privilege-granting NFTs should exercise due diligence when evaluating staking providers. Signs of mismanagement or fraud should be carefully assessed. The interface itself does not enable new manipulation capabilities, but caution is always prudent when interacting with smart contracts and staking pools. ## Copyright From 80b8ee34196def55e070dc9f7b9b7fc0a38532da Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 08:47:47 -0800 Subject: [PATCH 06/13] Minor improvement to the comments in the interface --- ERCS/erc-7531.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index e00003d0aa..5f1cfa9579 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -39,7 +39,7 @@ The interface is defined as follows: ```solidity interface IERC7531 { // This event MUST be emitted when the token's technical owner (i.e., the contract holding the token) - // differs from the actual owner (i.e., the entity with rights to the token). This distinction is + // differs from the actual owner (i.e., the entity with rights over the token). This distinction is // particularly relevant for staked tokens, where the technical owner is typically the staking contract. // The event MUST be emitted in the same block as the Transfer event emitted by the ERC-721 contract or in // any following block. In any case, any new Transfer event involving the same token invalidates the From 461870ad022e30e84fa7f50eed4a4db09a29edbb Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 08:51:17 -0800 Subject: [PATCH 07/13] Adding comments in the interface to clarify it --- ERCS/erc-7531.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index 5f1cfa9579..f390b43e78 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -48,7 +48,11 @@ interface IERC7531 { // MUST check that the contract emitting the event is the current owner of the token. event HolderOfRightsFor(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); - // It MUST revert if the token is not staked + // @dev Returns the address of the entity with rights over the token, when it's not the current owner. + // It MUST revert if the token is not staked. + // @param tokenAddress The address of the ERC-721 contract. + // @param tokenId The ID of the token. + // @return The address of the entity with rights over the token. function holderOfRightsFor( address tokenAddress, uint256 tokenId From 81945cab8a01ead004c69ddf4d18c4a990eec2e0 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 14 Nov 2023 08:58:12 -0800 Subject: [PATCH 08/13] Minor clarification about the way to validate the event --- ERCS/erc-7531.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index f390b43e78..bc514400f1 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -45,7 +45,8 @@ interface IERC7531 { // any following block. In any case, any new Transfer event involving the same token invalidates the // previous HolderOfRightsFor event. // Since any smart contract could emit a fake HolderOfRightsFor event, entities listening to the event, - // MUST check that the contract emitting the event is the current owner of the token. + // MUST check that the contract emitting the event is consistent with the current owner of the token coming + // from the related Transfer event. event HolderOfRightsFor(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); // @dev Returns the address of the entity with rights over the token, when it's not the current owner. @@ -72,7 +73,7 @@ To maintain compatibility with the broader ecosystem and optimize for gas effici ### Important Consideration Regarding Event Authenticity: -Given that any smart contract has the ability to emit a `HolderOfRightsFor` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `HolderOfRightsFor` event is indeed the current holder (i.e., the technical owner) of the token in question. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. +Given that any smart contract has the ability to emit a `HolderOfRightsFor` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `HolderOfRightsFor` event is indeed the current holder (i.e., the technical owner) of the token in question, for example, comparing the emitting contract with the owner resulting from the most recent `Transfer` event. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. ## Rationale From 944fafd14b3ff488e9d0ea68b4f398acc227a09f Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Thu, 16 Nov 2023 20:12:26 -0800 Subject: [PATCH 09/13] Update title --- ERCS/erc-7531.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index bc514400f1..28e37dad95 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -1,6 +1,6 @@ --- eip: 7531 -title: Getting Staked ERC-721 Ownership Recognition +title: Staked ERC-721 Ownership Recognition description: Recognizing NFT ownership when staked into other contracts. author: Francesco Sullo (@sullof) discussions-to: https://ethereum-magicians.org/t/eip-7531-resolving-staked-erc-721-ownership-recognition/15967 From 704ffa37f27b76117975205bcae831511027982b Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 21 Nov 2023 12:29:26 -0800 Subject: [PATCH 10/13] Using held instead of staked for clarity and consistency --- ERCS/erc-7531.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index bc514400f1..66e1cbec65 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -50,7 +50,7 @@ interface IERC7531 { event HolderOfRightsFor(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); // @dev Returns the address of the entity with rights over the token, when it's not the current owner. - // It MUST revert if the token is not staked. + // It MUST revert if the token is not held. // @param tokenAddress The address of the ERC-721 contract. // @param tokenId The ID of the token. // @return The address of the entity with rights over the token. @@ -61,11 +61,11 @@ interface IERC7531 { } ``` -The `HolderOfRightsFor` event is crucial for accurately identifying the actual owner of a staked token. In scenarios where a token is staked in a contract, the [ERC-721](./eip-721.md) Transfer event would incorrectly assign ownership to the staking contract itself. The `HolderOfRightsFor` event addresses this discrepancy by explicitly signaling the real owner of the token rights. +The `HolderOfRightsFor` event is crucial for accurately identifying the actual owner of a held token. In scenarios where a token is staked in a contract, the [ERC-721](./eip-721.md) Transfer event would incorrectly assign ownership to the staking contract itself. The `HolderOfRightsFor` event addresses this discrepancy by explicitly signaling the real owner of the token rights. ### Timing of Event Emission: -The `HolderOfRightsFor` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of staked tokens. +The `HolderOfRightsFor` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, staking pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of held tokens. ### Invalidation of Previous HolderOfRightsFor Events: @@ -83,7 +83,7 @@ Non-lockable NFTs present a unique challenge in decentralized ecosystems, especi ### The holderOfRightsFor Method: -The `holderOfRightsFor` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is staked in a pool. +The `holderOfRightsFor` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is held in a pool. ### Technical Advantages: From dbeefead8307f21a604ba05c94cf0f7b157a79e6 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Tue, 21 Nov 2023 12:37:03 -0800 Subject: [PATCH 11/13] Minor clarification in the comment to the HolderOfRightsFor event --- ERCS/erc-7531.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index 9646e6c36c..2ff938f6bb 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -42,7 +42,7 @@ interface IERC7531 { // differs from the actual owner (i.e., the entity with rights over the token). This distinction is // particularly relevant for staked tokens, where the technical owner is typically the staking contract. // The event MUST be emitted in the same block as the Transfer event emitted by the ERC-721 contract or in - // any following block. In any case, any new Transfer event involving the same token invalidates the + // any following block. In any case, any later Transfer event involving the same token invalidates the // previous HolderOfRightsFor event. // Since any smart contract could emit a fake HolderOfRightsFor event, entities listening to the event, // MUST check that the contract emitting the event is consistent with the current owner of the token coming From 4f7d5b43a6e4de2ffabe906eb167c72489be17a4 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Mon, 27 Nov 2023 15:39:42 -0800 Subject: [PATCH 12/13] Changing function and event name in the interface --- ERCS/erc-7531.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index 2ff938f6bb..5187f7f803 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -43,37 +43,37 @@ interface IERC7531 { // particularly relevant for staked tokens, where the technical owner is typically the staking contract. // The event MUST be emitted in the same block as the Transfer event emitted by the ERC-721 contract or in // any following block. In any case, any later Transfer event involving the same token invalidates the - // previous HolderOfRightsFor event. - // Since any smart contract could emit a fake HolderOfRightsFor event, entities listening to the event, + // previous RightsHolderChange event. + // Since any smart contract could emit a fake RightsHolderChange event, entities listening to the event, // MUST check that the contract emitting the event is consistent with the current owner of the token coming // from the related Transfer event. - event HolderOfRightsFor(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); + event RightsHolderChange(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); // @dev Returns the address of the entity with rights over the token, when it's not the current owner. // It MUST revert if the token is not held. // @param tokenAddress The address of the ERC-721 contract. // @param tokenId The ID of the token. // @return The address of the entity with rights over the token. - function holderOfRightsFor( + function rightsHolderOf( address tokenAddress, uint256 tokenId ) external view returns (address); } ``` -The `HolderOfRightsFor` event is crucial for accurately identifying the actual owner of a held token. In scenarios where a token is staked in a contract, the [ERC-721](./eip-721.md) Transfer event would incorrectly assign ownership to the staking contract itself. The `HolderOfRightsFor` event addresses this discrepancy by explicitly signaling the real owner of the token rights. +The `RightsHolderChange` event is crucial for accurately identifying the actual owner of a held token. In scenarios where a token is staked in a contract, the [ERC-721](./eip-721.md) Transfer event would incorrectly assign ownership to the staking contract itself. The `RightsHolderChange` event addresses this discrepancy by explicitly signaling the real owner of the token rights. ### Timing of Event Emission: -The `HolderOfRightsFor` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, staking pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of held tokens. +The `RightsHolderChange` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, staking pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of held tokens. -### Invalidation of Previous HolderOfRightsFor Events: +### Invalidation of Previous RightsHolderChange Events: -To maintain compatibility with the broader ecosystem and optimize for gas efficiency, any new `Transfer` event involving the same token invalidates the previous `HolderOfRightsFor` event. This approach ensures that the most recent `Transfer` event reliably reflects the current ownership status, negating the need for additional events upon unstaking. +To maintain compatibility with the broader ecosystem and optimize for gas efficiency, any new `Transfer` event involving the same token invalidates the previous `RightsHolderChange` event. This approach ensures that the most recent `Transfer` event reliably reflects the current ownership status, negating the need for additional events upon unstaking. ### Important Consideration Regarding Event Authenticity: -Given that any smart contract has the ability to emit a `HolderOfRightsFor` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `HolderOfRightsFor` event is indeed the current holder (i.e., the technical owner) of the token in question, for example, comparing the emitting contract with the owner resulting from the most recent `Transfer` event. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. +Given that any smart contract has the ability to emit a `RightsHolderChange` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `RightsHolderChange` event is indeed the current holder (i.e., the technical owner) of the token in question, for example, comparing the emitting contract with the owner resulting from the most recent `Transfer` event. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. ## Rationale @@ -81,9 +81,9 @@ Given that any smart contract has the ability to emit a `HolderOfRightsFor` even Non-lockable NFTs present a unique challenge in decentralized ecosystems, especially in scenarios involving staking or delegating usage rights. The standard ERC-721 ownerOf function returns the current owner of the NFT, which, in the case of staking, would be the staking pool contract. This transfer of ownership to the staking pool, even if temporary, can disrupt the utility or privileges tied to the NFT, such as participation in governance, access to exclusive content, or utility within a specific ecosystem. -### The holderOfRightsFor Method: +### The rightsHolderOf Method: -The `holderOfRightsFor` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is held in a pool. +The `rightsHolderOf` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is held in a pool. ### Technical Advantages: @@ -93,7 +93,7 @@ The `holderOfRightsFor` method provides a solution to this challenge. By maintai 3. Compatibility and Interoperability: By introducing a new method instead of altering the existing ownerOf function, this EIP ensures backward compatibility with existing ERC-721 contracts. This is crucial for maintaining interoperability across various platforms and applications in the NFT space. -4. Event-Driven Updates: The `HolderOfRightsFor` event facilitates real-time tracking of the rights-holder of an NFT. This is particularly useful for third-party platforms and services that rely on up-to-date ownership information to provide services or privileges. +4. Event-Driven Updates: The `RightsHolderChange` event facilitates real-time tracking of the rights-holder of an NFT. This is particularly useful for third-party platforms and services that rely on up-to-date ownership information to provide services or privileges. ### Addressing Potential Misuse: @@ -109,7 +109,7 @@ A potential risk with this interface is the improper assignment of ownership by ### Event Authenticity: -There is a concern regarding the potential emission of fake `HolderOfRightsFor` events. Since any contract can emit such an event, there's a risk of misinformation or misrepresentation of ownership. It is crucial for entities listening to the `HolderOfRightsFor` event to verify that the emitting contract is indeed the current owner of the token. This validation is essential to ensure the accuracy of ownership information and to mitigate the risks associated with deceptive event emissions. +There is a concern regarding the potential emission of fake `RightsHolderChange` events. Since any contract can emit such an event, there's a risk of misinformation or misrepresentation of ownership. It is crucial for entities listening to the `RightsHolderChange` event to verify that the emitting contract is indeed the current owner of the token. This validation is essential to ensure the accuracy of ownership information and to mitigate the risks associated with deceptive event emissions. ### Reducing the Risk of Inaccurate Ownership Records: From a3a3ce9127e864f940497a02f89d17ca59c48b26 Mon Sep 17 00:00:00 2001 From: Francesco Sullo Date: Mon, 27 Nov 2023 17:24:07 -0800 Subject: [PATCH 13/13] Fixed issues --- ERCS/erc-7531.md | 49 +++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/ERCS/erc-7531.md b/ERCS/erc-7531.md index 5187f7f803..b188bad970 100644 --- a/ERCS/erc-7531.md +++ b/ERCS/erc-7531.md @@ -38,22 +38,29 @@ The interface is defined as follows: ```solidity interface IERC7531 { - // This event MUST be emitted when the token's technical owner (i.e., the contract holding the token) - // differs from the actual owner (i.e., the entity with rights over the token). This distinction is - // particularly relevant for staked tokens, where the technical owner is typically the staking contract. - // The event MUST be emitted in the same block as the Transfer event emitted by the ERC-721 contract or in - // any following block. In any case, any later Transfer event involving the same token invalidates the - // previous RightsHolderChange event. - // Since any smart contract could emit a fake RightsHolderChange event, entities listening to the event, - // MUST check that the contract emitting the event is consistent with the current owner of the token coming - // from the related Transfer event. + /** + * @dev Emitted when the token's technical owner (the contract holding the token) is different + * from its actual owner (the entity with rights over the token). This scenario is common + * in staking, where a staking contract is the technical owner. The event MUST be emitted + * in the same or any subsequent block as the Transfer event for the token. + * A later Transfer event involving the same token supersedes this RightsHolderChange event. + * To ensure authenticity, entities listening to this event MUST verify that the contract emitting + * the event matches the token's current owner as per the related Transfer event. + * + * @param tokenAddress The address of the token contract. + * @param tokenId The ID of the token. + * @param holder The address of the actual rights holder of the token. + */ event RightsHolderChange(address indexed tokenAddress, uint256 indexed tokenId, address indexed holder); - - // @dev Returns the address of the entity with rights over the token, when it's not the current owner. - // It MUST revert if the token is not held. - // @param tokenAddress The address of the ERC-721 contract. - // @param tokenId The ID of the token. - // @return The address of the entity with rights over the token. + + /** + * @dev Returns the address of the entity with rights over the token, distinct from the current owner. + * The function MUST revert if the token does not exist or is not currently held. + * + * @param tokenAddress The address of the ERC-721 contract. + * @param tokenId The ID of the token. + * @return The address of the entity with rights over the token. + */ function rightsHolderOf( address tokenAddress, uint256 tokenId @@ -67,21 +74,17 @@ The `RightsHolderChange` event is crucial for accurately identifying the actual The `RightsHolderChange` event MUST be emitted either in the same block as the corresponding Transfer event or in any subsequent block. This approach offers flexibility for existing pools to upgrade their systems without compromising past compatibility. Specifically, staking pools can emit this event for all previously staked tokens, or they can allow users to actively reclaim their ownership. In the latter case, the event SHOULD be emitted as part of the ownership reclamation process. This flexibility ensures that the system can adapt to both current and future states while accurately reflecting the actual ownership of held tokens. -### Invalidation of Previous RightsHolderChange Events: +### Invalidation of Previous `RightsHolderChange` Events: To maintain compatibility with the broader ecosystem and optimize for gas efficiency, any new `Transfer` event involving the same token invalidates the previous `RightsHolderChange` event. This approach ensures that the most recent `Transfer` event reliably reflects the current ownership status, negating the need for additional events upon unstaking. -### Important Consideration Regarding Event Authenticity: - -Given that any smart contract has the ability to emit a `RightsHolderChange` event, it is crucial for entities relying on these events to validate their authenticity. Specifically, entities should verify that the contract emitting a `RightsHolderChange` event is indeed the current holder (i.e., the technical owner) of the token in question, for example, comparing the emitting contract with the owner resulting from the most recent `Transfer` event. This verification step is essential to ensure that the information provided by the event is accurate and not fabricated by an unauthorized source. - ## Rationale ### Addressing Non-Lockable NFT Challenges: -Non-lockable NFTs present a unique challenge in decentralized ecosystems, especially in scenarios involving staking or delegating usage rights. The standard ERC-721 ownerOf function returns the current owner of the NFT, which, in the case of staking, would be the staking pool contract. This transfer of ownership to the staking pool, even if temporary, can disrupt the utility or privileges tied to the NFT, such as participation in governance, access to exclusive content, or utility within a specific ecosystem. +Non-lockable NFTs present a unique challenge in decentralized ecosystems, especially in scenarios involving staking or delegating usage rights. The standard [ERC-721](./eip-721.md) `ownerOf` function returns the current owner of the NFT, which, in the case of staking, would be the staking pool contract. This transfer of ownership to the staking pool, even if temporary, can disrupt the utility or privileges tied to the NFT, such as participation in governance, access to exclusive content, or utility within a specific ecosystem. -### The rightsHolderOf Method: +### The `rightsHolderOf` Method: The `rightsHolderOf` method provides a solution to this challenge. By maintaining a record of the original owner or the rightful holder of certain privileges associated with the NFT, this method ensures that the underlying utility of the NFT is preserved, even when the NFT itself is held in a pool. @@ -91,7 +94,7 @@ The `rightsHolderOf` method provides a solution to this challenge. By maintainin 2. Enhanced Flexibility: The method offers greater flexibility for NFT owners, allowing them to participate in staking and other DeFi activities without relinquishing the intrinsic benefits of their NFTs. -3. Compatibility and Interoperability: By introducing a new method instead of altering the existing ownerOf function, this EIP ensures backward compatibility with existing ERC-721 contracts. This is crucial for maintaining interoperability across various platforms and applications in the NFT space. +3. Compatibility and Interoperability: By introducing a new method instead of altering the existing ownerOf function, this EIP ensures backward compatibility with existing [ERC-721](./eip-721.md) contracts. This is crucial for maintaining interoperability across various platforms and applications in the NFT space. 4. Event-Driven Updates: The `RightsHolderChange` event facilitates real-time tracking of the rights-holder of an NFT. This is particularly useful for third-party platforms and services that rely on up-to-date ownership information to provide services or privileges.