From 783c85c6a4dc37d1dd53415569b4c64244e560a2 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sun, 25 Feb 2024 02:12:30 +0800 Subject: [PATCH 01/28] ERC-721 Multi-Attribute Extension --- ERCS/erc-9999.txt | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 ERCS/erc-9999.txt diff --git a/ERCS/erc-9999.txt b/ERCS/erc-9999.txt new file mode 100644 index 0000000000..9464197203 --- /dev/null +++ b/ERCS/erc-9999.txt @@ -0,0 +1,39 @@ +--- +eip: xxxx +title: ERC-721 Multi-Attribute Extension +description: This is the draft. +author: Chen Liaoyuan (@chenly) +discussions-to: https://ethereum-magicians.org/t/erc-xxxx-erc-721-multi-attribute-extension/12345 +status: Draft +type: Standards Track +category: ERC +created: 2024-02-25 +requires: 721 +--- + +## Abstract + +This extension allows NFTs to have multiple attributes and enables the transfer of attribute values. + +## 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. + +Implementers of this extension **MUST** have all of the following functions: + + +## Rationale + +Nil + +## Backwards Compatibility + +This standard is fully [ERC-721](./eip-721.md) compatible. + +## Security Considerations + +Nil + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From c09abafc5a028d4137a93ad7e18c3d5b618d46e4 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sun, 25 Feb 2024 11:42:11 +0800 Subject: [PATCH 02/28] update --- ERCS/{erc-9999.txt => erc-9999.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename ERCS/{erc-9999.txt => erc-9999.md} (96%) diff --git a/ERCS/erc-9999.txt b/ERCS/erc-9999.md similarity index 96% rename from ERCS/erc-9999.txt rename to ERCS/erc-9999.md index 9464197203..97a0d02649 100644 --- a/ERCS/erc-9999.txt +++ b/ERCS/erc-9999.md @@ -1,7 +1,7 @@ --- eip: xxxx title: ERC-721 Multi-Attribute Extension -description: This is the draft. +description: This is a draft. author: Chen Liaoyuan (@chenly) discussions-to: https://ethereum-magicians.org/t/erc-xxxx-erc-721-multi-attribute-extension/12345 status: Draft From 66a2bd3a93133e231088032cc31a3c259528e3d2 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Tue, 27 Feb 2024 23:59:44 +0800 Subject: [PATCH 03/28] Named Token --- ERCS/erc-9999.md | 124 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 116 insertions(+), 8 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 97a0d02649..48477cd5f7 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -1,19 +1,19 @@ --- -eip: xxxx -title: ERC-721 Multi-Attribute Extension -description: This is a draft. +eip: 9999 +title: Named Token, an Extension of ERC-721 +description: Add a unique name to ERC-721 tokens. author: Chen Liaoyuan (@chenly) -discussions-to: https://ethereum-magicians.org/t/erc-xxxx-erc-721-multi-attribute-extension/12345 +discussions-to: https://ethereum-magicians.org/t/erc-9999-name-token/12345 status: Draft type: Standards Track category: ERC -created: 2024-02-25 +created: 2024-02-27 requires: 721 --- ## Abstract -This extension allows NFTs to have multiple attributes and enables the transfer of attribute values. +This standard is an extension of ERC-721. It allows each token to have a unique name, enabling direct queries of token ownership by name and permitting owners to set or change the names of their tokens. ## Specification @@ -21,19 +21,127 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S Implementers of this extension **MUST** have all of the following functions: +```solidity +pragma solidity ^0.8.0; + +interface NamedToken { + /** + * @dev Returns the name of the specified token. + * @param tokenId uint256 ID of the token to query + * @return name string representing the name of the given token ID + */ + function name(uint256 tokenId) external view returns (string memory); + + /** + * @dev Returns the owner of the specified token name. + * @param name string name of the token to query + * @return owner address representing the owner of the given token name + */ + function ownerOf(string memory name) external view returns (address); + + /** + * @dev Mints a new token with a name to a specified address. This function is typically internal and might not + * appear in the interface but is described here for completeness. + * @param to address of the future owner of the token + * @param tokenId uint256 ID of the token to be minted + * @param name string name to be assigned to this token + */ + // function _mint(address to, uint256 tokenId, string memory name) internal; + + /** + * @dev Sets a name for a given token. + * @param tokenId uint256 ID of the token to set its name + * @param name string name to be set to the token + */ + function setName(uint256 tokenId, string memory name) external; +} +``` ## Rationale -Nil +As mentioned in the abstract, this EIP’s goal is to have a simple interface for supporting Named Token. Here are a few design decisions and why they were made: ## Backwards Compatibility This standard is fully [ERC-721](./eip-721.md) compatible. +## Reference Implementation + +```solidity +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/utils/Strings.sol"; + +contract NamedToken is ERC721 { + using Strings for uint256; + + // Mapping from token ID to name + mapping(uint256 => string) private _tokenNames; + + // Mapping from name to token ID + mapping(string => uint256) private _nameToTokenId; + + /** + * @dev Returns the name of the specified token. + * @param tokenId uint256 ID of the token to query + * @return name string representing the name of the given token ID + */ + function name(uint256 tokenId) public view returns (string memory) { + require(_exists(tokenId), "ERC721NamedExtension: Name query for nonexistent token"); + return _tokenNames[tokenId]; + } + + /** + * @dev Returns the owner of the specified token name. + * @param name string name of the token to query + * @return owner address representing the owner of the given token name + */ + function ownerOf(string memory name) public view returns (address) { + uint256 tokenId = _nameToTokenId[name]; + require(_exists(tokenId), "ERC721NamedExtension: Owner query for nonexistent name"); + return ownerOf(tokenId); + } + + /** + * @dev Internal function to mint a new token with a name. + * @param to address of the future owner of the token + * @param tokenId uint256 ID of the token to be minted + * @param name string name to be assigned to this token + */ + function _mint(address to, uint256 tokenId, string memory name) internal virtual { + super._mint(to, tokenId); // Call the inherited _mint function + _setTokenName(tokenId, name); + } + + /** + * @dev Public function to set a name for a token. + * @param tokenId uint256 ID of the token to set its name + * @param name string name to be set to the token + */ + function setName(uint256 tokenId, string memory name) public { + require(_exists(tokenId), "ERC721NamedExtension: Set name for nonexistent token"); + require(ownerOf(tokenId) == msg.sender, "ERC721NamedExtension: Caller is not the token owner"); + + _setTokenName(tokenId, name); + } + + /** + * @dev Internal function to set the token name. + * @param tokenId uint256 ID of the token + * @param name string name to be assigned to the token + */ + function _setTokenName(uint256 tokenId, string memory name) internal { + _tokenNames[tokenId] = name; + _nameToTokenId[name] = tokenId; + } +} +``` + ## Security Considerations Nil ## Copyright -Copyright and related rights waived via [CC0](../LICENSE.md). +Copyright and related rights waived via [CC0](../LICENSE.md). \ No newline at end of file From bd0a5eb4c92f7cc656ccd2604a33dde73ddfbb78 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 00:11:20 +0800 Subject: [PATCH 04/28] add --- ERCS/erc-9999.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 48477cd5f7..561e1c6347 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -61,6 +61,14 @@ interface NamedToken { As mentioned in the abstract, this EIP’s goal is to have a simple interface for supporting Named Token. Here are a few design decisions and why they were made: +### Intuitive Token IDs + +Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the ERC-721 standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. + +### Expanding NFT Use Cases + +By allowing each token to possess a unique name, we unlock new application scenarios in ecosystems built around scarce username resources, such as domain name registration systems. In such scenarios, domain owners can demonstrate ownership directly by holding the corresponding token, thereby broadening the application spectrum and enhancing the value of NFTs. + ## Backwards Compatibility This standard is fully [ERC-721](./eip-721.md) compatible. From 28a776535ae1839d21a57f0cecb62bef17d0783f Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 00:15:20 +0800 Subject: [PATCH 05/28] \ --- ERCS/erc-9999.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 561e1c6347..5e44562c27 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -13,7 +13,7 @@ requires: 721 ## Abstract -This standard is an extension of ERC-721. It allows each token to have a unique name, enabling direct queries of token ownership by name and permitting owners to set or change the names of their tokens. +This standard is an extension of [ERC-721](./eip-721.md). It allows each token to have a unique name, enabling direct queries of token ownership by name and permitting owners to set or change the names of their tokens. ## Specification @@ -63,7 +63,7 @@ As mentioned in the abstract, this EIP’s goal is to have a simple interface fo ### Intuitive Token IDs -Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the ERC-721 standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. +Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the [ERC-721](./eip-721.md) standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. ### Expanding NFT Use Cases From 4e2362ef47d0bc67597d859d00f7f4d8f90ae425 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 00:17:13 +0800 Subject: [PATCH 06/28] / --- ERCS/erc-9999.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 5e44562c27..53879dc562 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -24,7 +24,7 @@ Implementers of this extension **MUST** have all of the following functions: ```solidity pragma solidity ^0.8.0; -interface NamedToken { +interface NamedToken /* is IERC721 */ { /** * @dev Returns the name of the specified token. * @param tokenId uint256 ID of the token to query From 9c0e9fe56d3d02fb89901391e0601fb793dd490a Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 00:25:30 +0800 Subject: [PATCH 07/28] \ --- ERCS/erc-9999.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 53879dc562..b25d2632b9 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -59,7 +59,7 @@ interface NamedToken /* is IERC721 */ { ## Rationale -As mentioned in the abstract, this EIP’s goal is to have a simple interface for supporting Named Token. Here are a few design decisions and why they were made: +Here are a few design decisions and why they were made: ### Intuitive Token IDs @@ -148,7 +148,7 @@ contract NamedToken is ERC721 { ## Security Considerations -Nil +No security considerations were found. ## Copyright From a382107bfc59ab3dc018c19a5b581349fcab1dc8 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 00:57:57 +0800 Subject: [PATCH 08/28] \ --- ERCS/erc-9999.md | 54 ++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index b25d2632b9..a62a0ade52 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -34,26 +34,26 @@ interface NamedToken /* is IERC721 */ { /** * @dev Returns the owner of the specified token name. - * @param name string name of the token to query + * @param _name string name of the token to query * @return owner address representing the owner of the given token name */ - function ownerOf(string memory name) external view returns (address); + function ownerOf(string memory _name) external view returns (address); /** * @dev Mints a new token with a name to a specified address. This function is typically internal and might not * appear in the interface but is described here for completeness. * @param to address of the future owner of the token * @param tokenId uint256 ID of the token to be minted - * @param name string name to be assigned to this token + * @param _name string name to be assigned to this token */ - // function _mint(address to, uint256 tokenId, string memory name) internal; + // function _mint(address to, uint256 tokenId, string memory _name) internal; /** * @dev Sets a name for a given token. * @param tokenId uint256 ID of the token to set its name - * @param name string name to be set to the token + * @param _name string name to be set to the token */ - function setName(uint256 tokenId, string memory name) external; + function setName(uint256 tokenId, string memory _name) external; } ``` @@ -79,7 +79,6 @@ This standard is fully [ERC-721](./eip-721.md) compatible. pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; contract NamedToken is ERC721 { using Strings for uint256; @@ -90,24 +89,26 @@ contract NamedToken is ERC721 { // Mapping from name to token ID mapping(string => uint256) private _nameToTokenId; + constructor() + ERC721("NamedToken", "NTK"){} + /** * @dev Returns the name of the specified token. * @param tokenId uint256 ID of the token to query * @return name string representing the name of the given token ID */ function name(uint256 tokenId) public view returns (string memory) { - require(_exists(tokenId), "ERC721NamedExtension: Name query for nonexistent token"); return _tokenNames[tokenId]; } /** * @dev Returns the owner of the specified token name. - * @param name string name of the token to query + * @param _name string name of the token to query * @return owner address representing the owner of the given token name */ - function ownerOf(string memory name) public view returns (address) { - uint256 tokenId = _nameToTokenId[name]; - require(_exists(tokenId), "ERC721NamedExtension: Owner query for nonexistent name"); + function ownerOf(string memory _name) public view returns (address) { + uint256 tokenId = _nameToTokenId[_name]; + require(tokenId>0, "ERC721NamedExtension: Owner query for nonexistent name"); return ownerOf(tokenId); } @@ -115,33 +116,36 @@ contract NamedToken is ERC721 { * @dev Internal function to mint a new token with a name. * @param to address of the future owner of the token * @param tokenId uint256 ID of the token to be minted - * @param name string name to be assigned to this token + * @param _name string name to be assigned to this token */ - function _mint(address to, uint256 tokenId, string memory name) internal virtual { + function _mint(address to, uint256 tokenId, string memory _name) internal virtual { super._mint(to, tokenId); // Call the inherited _mint function - _setTokenName(tokenId, name); + _setTokenName(tokenId, _name); } /** * @dev Public function to set a name for a token. * @param tokenId uint256 ID of the token to set its name - * @param name string name to be set to the token + * @param _name string name to be set to the token */ - function setName(uint256 tokenId, string memory name) public { - require(_exists(tokenId), "ERC721NamedExtension: Set name for nonexistent token"); + function setName(uint256 tokenId, string memory _name) public { require(ownerOf(tokenId) == msg.sender, "ERC721NamedExtension: Caller is not the token owner"); - - _setTokenName(tokenId, name); + _setTokenName(tokenId, _name); } /** - * @dev Internal function to set the token name. + * @dev Internal function to safely set the token name with uniqueness check. * @param tokenId uint256 ID of the token - * @param name string name to be assigned to the token + * @param _name string name to be assigned to the token */ - function _setTokenName(uint256 tokenId, string memory name) internal { - _tokenNames[tokenId] = name; - _nameToTokenId[name] = tokenId; + function _setTokenName(uint256 tokenId, string memory _name) internal { + require(_nameToTokenId[_name] == 0 || _nameToTokenId[_name] == tokenId, "ERC721NamedExtension: Name already in use"); + // Remove the old name mapping if exists + if(bytes(_tokenNames[tokenId]).length > 0) { + delete _nameToTokenId[_tokenNames[tokenId]]; + } + _tokenNames[tokenId] = _name; + _nameToTokenId[_name] = tokenId; } } ``` From c77be047d7b064c0810428bc34b0b5ae85b33969 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 01:21:47 +0800 Subject: [PATCH 09/28] \ --- ERCS/erc-9999.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index a62a0ade52..f179c70f58 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -81,7 +81,6 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract NamedToken is ERC721 { - using Strings for uint256; // Mapping from token ID to name mapping(uint256 => string) private _tokenNames; From 977ff3bafc0116a98d4b29714690627351cde0d9 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Wed, 28 Feb 2024 01:47:54 +0800 Subject: [PATCH 10/28] \ --- ERCS/erc-9999.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index f179c70f58..ddf58a2146 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -24,7 +24,12 @@ Implementers of this extension **MUST** have all of the following functions: ```solidity pragma solidity ^0.8.0; -interface NamedToken /* is IERC721 */ { +interface INamedToken { + // Events + event TokenNamed(uint256 indexed tokenId, string newName); + event TokenMintedWithName(address indexed to, uint256 indexed tokenId, string name); + event NameChanged(uint256 indexed tokenId, string oldName, string newName); + /** * @dev Returns the name of the specified token. * @param tokenId uint256 ID of the token to query @@ -82,14 +87,18 @@ import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract NamedToken is ERC721 { + // Event declarations + event TokenNamed(uint256 indexed tokenId, string newName); + event TokenMintedWithName(address indexed to, uint256 indexed tokenId, string name); + event NameChanged(uint256 indexed tokenId, string oldName, string newName); + // Mapping from token ID to name mapping(uint256 => string) private _tokenNames; // Mapping from name to token ID mapping(string => uint256) private _nameToTokenId; - constructor() - ERC721("NamedToken", "NTK"){} + constructor() ERC721("NamedToken", "NTK") {} /** * @dev Returns the name of the specified token. @@ -107,7 +116,7 @@ contract NamedToken is ERC721 { */ function ownerOf(string memory _name) public view returns (address) { uint256 tokenId = _nameToTokenId[_name]; - require(tokenId>0, "ERC721NamedExtension: Owner query for nonexistent name"); + require(tokenId > 0, "ERC721NamedExtension: Owner query for nonexistent name"); return ownerOf(tokenId); } @@ -120,6 +129,7 @@ contract NamedToken is ERC721 { function _mint(address to, uint256 tokenId, string memory _name) internal virtual { super._mint(to, tokenId); // Call the inherited _mint function _setTokenName(tokenId, _name); + emit TokenMintedWithName(to, tokenId, _name); } /** @@ -129,7 +139,13 @@ contract NamedToken is ERC721 { */ function setName(uint256 tokenId, string memory _name) public { require(ownerOf(tokenId) == msg.sender, "ERC721NamedExtension: Caller is not the token owner"); + string memory oldName = _tokenNames[tokenId]; _setTokenName(tokenId, _name); + if(bytes(oldName).length > 0) { + emit NameChanged(tokenId, oldName, _name); + } else { + emit TokenNamed(tokenId, _name); + } } /** From 988c502256c777beb5ffac7718cbe11d894d0a34 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Fri, 1 Mar 2024 01:47:12 +0800 Subject: [PATCH 11/28] add NameRegistry --- ERCS/erc-9999.md | 184 ++++++++++++++++++++++++----------------------- 1 file changed, 95 insertions(+), 89 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index ddf58a2146..be85dcae08 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -1,19 +1,19 @@ --- eip: 9999 -title: Named Token, an Extension of ERC-721 -description: Add a unique name to ERC-721 tokens. +title: ERC-721 Name Registry Extension +description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. author: Chen Liaoyuan (@chenly) -discussions-to: https://ethereum-magicians.org/t/erc-9999-name-token/12345 +discussions-to: https://ethereum-magicians.org/t/erc-9999/12345 status: Draft type: Standards Track category: ERC -created: 2024-02-27 +created: 2024-03-01 requires: 721 --- ## Abstract -This standard is an extension of [ERC-721](./eip-721.md). It allows each token to have a unique name, enabling direct queries of token ownership by name and permitting owners to set or change the names of their tokens. +This standard enhances [ERC-721](./eip-721.md) by giving each token a unique name and an expiry date, allowing other token holders to claim the name once it expires. ## Specification @@ -22,43 +22,65 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S Implementers of this extension **MUST** have all of the following functions: ```solidity +// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -interface INamedToken { - // Events - event TokenNamed(uint256 indexed tokenId, string newName); - event TokenMintedWithName(address indexed to, uint256 indexed tokenId, string name); - event NameChanged(uint256 indexed tokenId, string oldName, string newName); +/** + * @title INameRegistry + * @dev Interface for the NameRegistry smart contract. + * This interface allows interaction with a NameRegistry, + * enabling the registration, management, and lookup of names + * with associated expiry dates tied to specific tokens. + */ +interface INameRegistry { + /** + * @dev Emitted when a token is named. + * @param tokenId The token ID that is being named. + * @param newName The new name assigned to the token. + * @param expiryDate The expiry date of the name registration. + */ + event TokenNamed(uint256 indexed tokenId, bytes32 newName, uint256 expiryDate); + + /** + * @dev Emitted when a token with a name is minted. + * @param to The address of the token recipient. + * @param tokenId The token ID that is minted. + * @param name The name assigned to the newly minted token. + * @param expiryDate The expiry date of the name registration. + */ + event TokenMintedWithName(address indexed to, uint256 indexed tokenId, bytes32 name, uint256 expiryDate); /** - * @dev Returns the name of the specified token. - * @param tokenId uint256 ID of the token to query - * @return name string representing the name of the given token ID + * @dev Emitted when the name of a token is changed. + * @param tokenId The token ID whose name is changed. + * @param oldName The previous name of the token. + * @param newName The new name assigned to the token. + * @param expiryDate The expiry date of the new name registration. */ - function name(uint256 tokenId) external view returns (string memory); + event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate); /** - * @dev Returns the owner of the specified token name. - * @param _name string name of the token to query - * @return owner address representing the owner of the given token name + * @dev Returns the name of the specified token, if the name has not expired. + * @param tokenId The token ID to query for its name. + * @return The name of the token, or an empty bytes32 if no name is set or it has expired. */ - function ownerOf(string memory _name) external view returns (address); + function nameOf(uint256 tokenId) external view returns (bytes32); /** - * @dev Mints a new token with a name to a specified address. This function is typically internal and might not - * appear in the interface but is described here for completeness. - * @param to address of the future owner of the token - * @param tokenId uint256 ID of the token to be minted - * @param _name string name to be assigned to this token + * @dev Returns the token ID associated with a given name, if the name registration has not expired. + * @param _name The name to query for its associated token ID. + * @return The token ID associated with the name, or zero if no token is found or the name has expired. */ - // function _mint(address to, uint256 tokenId, string memory _name) internal; + function tokenIdOf(bytes32 _name) external view returns (uint256); /** - * @dev Sets a name for a given token. - * @param tokenId uint256 ID of the token to set its name - * @param _name string name to be set to the token + * @dev Allows a token owner to set or update the name of their token, subject to a duration for the name's validity. + * @param tokenId The token ID whose name is to be set or updated. + * @param _name The new name to assign to the token. + * @param duration The duration in seconds for which the name is valid, starting from the time of calling this function. + * Note: The name must be unique and not currently in use by an active (non-expired) registration. */ - function setName(uint256 tokenId, string memory _name) external; + function setName(uint256 tokenId, bytes32 _name, uint256 duration) external; } ``` @@ -85,89 +107,73 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -contract NamedToken is ERC721 { +contract NameRegistry is ERC721 { + event TokenNamed(uint256 indexed tokenId, bytes32 newName, uint256 expiryDate); + event TokenMintedWithName(address indexed to, uint256 indexed tokenId, bytes32 name, uint256 expiryDate); + event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate); - // Event declarations - event TokenNamed(uint256 indexed tokenId, string newName); - event TokenMintedWithName(address indexed to, uint256 indexed tokenId, string name); - event NameChanged(uint256 indexed tokenId, string oldName, string newName); + struct NameRegistration { + uint256 tokenId; + uint256 expiryDate; + } - // Mapping from token ID to name - mapping(uint256 => string) private _tokenNames; + mapping(uint256 => bytes32) private _tokenNames; + mapping(bytes32 => NameRegistration) private _nameRegistrations; + mapping(uint256 => uint256) private _lastSetNameTime; - // Mapping from name to token ID - mapping(string => uint256) private _nameToTokenId; + uint256 public constant MAX_DURATION = 10 * 365 days; + uint256 public constant MIN_SET_NAME_INTERVAL = 1 days; - constructor() ERC721("NamedToken", "NTK") {} + constructor() ERC721("NameRegistry", "NRG") {} - /** - * @dev Returns the name of the specified token. - * @param tokenId uint256 ID of the token to query - * @return name string representing the name of the given token ID - */ - function name(uint256 tokenId) public view returns (string memory) { + function nameOf(uint256 tokenId) public view returns (bytes32) { + require(_tokenNames[tokenId] != bytes32(0) && _nameRegistrations[_tokenNames[tokenId]].expiryDate > block.timestamp, "NameRegistry: Name expired or does not exist"); return _tokenNames[tokenId]; } - /** - * @dev Returns the owner of the specified token name. - * @param _name string name of the token to query - * @return owner address representing the owner of the given token name - */ - function ownerOf(string memory _name) public view returns (address) { - uint256 tokenId = _nameToTokenId[_name]; - require(tokenId > 0, "ERC721NamedExtension: Owner query for nonexistent name"); - return ownerOf(tokenId); + function tokenIdOf(bytes32 _name) public view returns (uint256) { + require(_nameRegistrations[_name].expiryDate > block.timestamp, "NameRegistry: Name expired"); + return _nameRegistrations[_name].tokenId; } - /** - * @dev Internal function to mint a new token with a name. - * @param to address of the future owner of the token - * @param tokenId uint256 ID of the token to be minted - * @param _name string name to be assigned to this token - */ - function _mint(address to, uint256 tokenId, string memory _name) internal virtual { - super._mint(to, tokenId); // Call the inherited _mint function - _setTokenName(tokenId, _name); - emit TokenMintedWithName(to, tokenId, _name); - } + function setName(uint256 tokenId, bytes32 _name, uint256 duration) public { + require(ownerOf(tokenId) == msg.sender, "NameRegistry: Caller is not the token owner"); + require(duration <= MAX_DURATION, "NameRegistry: Duration exceeds maximum limit"); + require(block.timestamp - _lastSetNameTime[tokenId] >= MIN_SET_NAME_INTERVAL, "NameRegistry: Minimum interval not met"); + + // Check if name is either not registered or expired + require(_nameRegistrations[_name].expiryDate <= block.timestamp, "NameRegistry: Name already in use and not expired"); - /** - * @dev Public function to set a name for a token. - * @param tokenId uint256 ID of the token to set its name - * @param _name string name to be set to the token - */ - function setName(uint256 tokenId, string memory _name) public { - require(ownerOf(tokenId) == msg.sender, "ERC721NamedExtension: Caller is not the token owner"); - string memory oldName = _tokenNames[tokenId]; - _setTokenName(tokenId, _name); - if(bytes(oldName).length > 0) { - emit NameChanged(tokenId, oldName, _name); + bytes32 oldName = _tokenNames[tokenId]; + uint256 expiryDate = block.timestamp + duration; + _setTokenName(tokenId, _name, expiryDate); + + if(oldName != bytes32(0)) { + emit NameChanged(tokenId, oldName, _name, expiryDate); } else { - emit TokenNamed(tokenId, _name); + emit TokenNamed(tokenId, _name, expiryDate); } + + _lastSetNameTime[tokenId] = block.timestamp; } - /** - * @dev Internal function to safely set the token name with uniqueness check. - * @param tokenId uint256 ID of the token - * @param _name string name to be assigned to the token - */ - function _setTokenName(uint256 tokenId, string memory _name) internal { - require(_nameToTokenId[_name] == 0 || _nameToTokenId[_name] == tokenId, "ERC721NamedExtension: Name already in use"); - // Remove the old name mapping if exists - if(bytes(_tokenNames[tokenId]).length > 0) { - delete _nameToTokenId[_tokenNames[tokenId]]; - } + function _mint(address to, uint256 tokenId, bytes32 _name, uint256 duration) internal virtual { + super._mint(to, tokenId); + uint256 expiryDate = block.timestamp + duration; + _setTokenName(tokenId, _name, expiryDate); + emit TokenMintedWithName(to, tokenId, _name, expiryDate); + } + + function _setTokenName(uint256 tokenId, bytes32 _name, uint256 expiryDate) internal { _tokenNames[tokenId] = _name; - _nameToTokenId[_name] = tokenId; + _nameRegistrations[_name] = NameRegistration(tokenId, expiryDate); } } ``` ## Security Considerations -No security considerations were found. +The implementation of minimum intervals for name setting and maximum expiry durations for names prevents abusive behaviors and resource hoarding, deters spam and malicious attacks by limiting rapid, consecutive transactions, and promotes the efficient and equitable use of naming resources. By ensuring that names cannot be monopolized indefinitely and that all actions are rate-limited, these guidelines not only mitigate potential security risks but also foster a more sustainable and fair environment for all participants in the ecosystem. ## Copyright From dbb08f3d7e1b456bdfd3880b88bb110df4b9ed0c Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Fri, 1 Mar 2024 02:01:30 +0800 Subject: [PATCH 12/28] update link --- ERCS/erc-9999.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index be85dcae08..f99aa40d8d 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -3,7 +3,7 @@ eip: 9999 title: ERC-721 Name Registry Extension description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. author: Chen Liaoyuan (@chenly) -discussions-to: https://ethereum-magicians.org/t/erc-9999/12345 +discussions-to: https://ethereum-magicians.org/t/erc-9999-erc-721-name-registry-extension/19005 status: Draft type: Standards Track category: ERC From bcee156b85cc6fd8b3342382190a6ab320a7997b Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Fri, 1 Mar 2024 12:25:57 +0800 Subject: [PATCH 13/28] add Security Considerations --- ERCS/erc-9999.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index f99aa40d8d..df4e4ff8e4 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -173,7 +173,13 @@ contract NameRegistry is ERC721 { ## Security Considerations -The implementation of minimum intervals for name setting and maximum expiry durations for names prevents abusive behaviors and resource hoarding, deters spam and malicious attacks by limiting rapid, consecutive transactions, and promotes the efficient and equitable use of naming resources. By ensuring that names cannot be monopolized indefinitely and that all actions are rate-limited, these guidelines not only mitigate potential security risks but also foster a more sustainable and fair environment for all participants in the ecosystem. +#### Mitigating Abusive Behaviors and Resource Hoarding + +The design includes mechanisms to prevent abusive behaviors and resource hoarding. Minimum intervals for name setting and maximum durations for name expiry are established to deter spam and malicious attacks, limit rapid consecutive name registrations, and encourage fair and efficient use of naming resources. These measures mitigate potential security risks, ensuring names cannot be monopolized indefinitely and promoting a sustainable and equitable environment for all users. + +#### Username Restrictions + +To facilitate indexing and gas efficiency, usernames should adhere to a length constraint of 3 to 32 characters. This range prevents the registration of overly long names, which can be costly in terms of gas and difficult to manage. Limiting characters to the range of [0-9a-z] enhances readability and prevents the abuse of the naming system by restricting the use of special characters that could complicate domain resolution or user recognition. Implementing these constraints not only promotes a high level of usability within the ecosystem but also guards against the proliferation of spam registrations, ensuring that the registry remains accessible and functional for genuine users. ## Copyright From 69246eb9aa38d684fb13f9d1b7aa1d2d0e109729 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Fri, 1 Mar 2024 13:00:44 +0800 Subject: [PATCH 14/28] \ --- ERCS/erc-9999.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index df4e4ff8e4..1277a4f20e 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -179,7 +179,7 @@ The design includes mechanisms to prevent abusive behaviors and resource hoardin #### Username Restrictions -To facilitate indexing and gas efficiency, usernames should adhere to a length constraint of 3 to 32 characters. This range prevents the registration of overly long names, which can be costly in terms of gas and difficult to manage. Limiting characters to the range of [0-9a-z] enhances readability and prevents the abuse of the naming system by restricting the use of special characters that could complicate domain resolution or user recognition. Implementing these constraints not only promotes a high level of usability within the ecosystem but also guards against the proliferation of spam registrations, ensuring that the registry remains accessible and functional for genuine users. +To facilitate indexing and gas efficiency, usernames should adhere to a length constraint of 3 to 32 characters. This range prevents the registration of overly long names, which can be costly in terms of gas and difficult to manage. Limiting characters to the range of [a-zA-Z0-9] enhances readability and prevents the abuse of the naming system by restricting the use of special characters that could complicate domain resolution or user recognition. Implementing these constraints not only promotes a high level of usability within the ecosystem but also guards against the proliferation of spam registrations, ensuring that the registry remains accessible and functional for genuine users. ## Copyright From 6eda2d36ecbc6e1254cf643f756235f9f13bf57a Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Fri, 1 Mar 2024 20:44:11 +0800 Subject: [PATCH 15/28] Update erc-9999.md --- ERCS/erc-9999.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ERCS/erc-9999.md b/ERCS/erc-9999.md index 1277a4f20e..dcda4e34f7 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-9999.md @@ -88,11 +88,11 @@ interface INameRegistry { Here are a few design decisions and why they were made: -### Intuitive Token IDs +#### Intuitive Token IDs Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the [ERC-721](./eip-721.md) standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. -### Expanding NFT Use Cases +#### Expanding NFT Use Cases By allowing each token to possess a unique name, we unlock new application scenarios in ecosystems built around scarce username resources, such as domain name registration systems. In such scenarios, domain owners can demonstrate ownership directly by holding the corresponding token, thereby broadening the application spectrum and enhancing the value of NFTs. @@ -183,4 +183,4 @@ To facilitate indexing and gas efficiency, usernames should adhere to a length c ## Copyright -Copyright and related rights waived via [CC0](../LICENSE.md). \ No newline at end of file +Copyright and related rights waived via [CC0](../LICENSE.md). From 638d085d2045a6e98fcc0f138663d26600955311 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 11:19:00 +0800 Subject: [PATCH 16/28] rename eip # --- ERCS/{erc-9999.md => erc-7644.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename ERCS/{erc-9999.md => erc-7644.md} (99%) diff --git a/ERCS/erc-9999.md b/ERCS/erc-7644.md similarity index 99% rename from ERCS/erc-9999.md rename to ERCS/erc-7644.md index dcda4e34f7..2d382f688f 100644 --- a/ERCS/erc-9999.md +++ b/ERCS/erc-7644.md @@ -1,5 +1,5 @@ --- -eip: 9999 +eip: 7644 title: ERC-721 Name Registry Extension description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. author: Chen Liaoyuan (@chenly) From c0872f1b82f0bf0bd3c806ed57084b3fda4e52d8 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 11:24:04 +0800 Subject: [PATCH 17/28] add link to topic --- ERCS/erc-7644.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 2d382f688f..f5cec643ee 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -1,9 +1,9 @@ --- eip: 7644 title: ERC-721 Name Registry Extension -description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. +description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. author: Chen Liaoyuan (@chenly) -discussions-to: https://ethereum-magicians.org/t/erc-9999-erc-721-name-registry-extension/19005 +discussions-to: https://ethereum-magicians.org/t/erc-7644-erc-721-name-registry-extension/19022 status: Draft type: Standards Track category: ERC From d31dc59b040c1659c569737cbdea9e5b6b9431c0 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 11:27:16 +0800 Subject: [PATCH 18/28] time-limited --- ERCS/erc-7644.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index f5cec643ee..c496f0be27 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -1,7 +1,7 @@ --- eip: 7644 title: ERC-721 Name Registry Extension -description: Add a Time-Limited unique naming registry mechanism to ERC-721 tokens. +description: Add a time-limited unique naming registry mechanism to ERC-721 tokens. author: Chen Liaoyuan (@chenly) discussions-to: https://ethereum-magicians.org/t/erc-7644-erc-721-name-registry-extension/19022 status: Draft From 061dd86ef0438e50ddd2b7b2b63e0d5e85bab160 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 12:33:00 +0800 Subject: [PATCH 19/28] add getName --- ERCS/erc-7644.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index c496f0be27..3a1d2563d3 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -81,6 +81,15 @@ interface INameRegistry { * Note: The name must be unique and not currently in use by an active (non-expired) registration. */ function setName(uint256 tokenId, bytes32 _name, uint256 duration) external; + + /** + * @dev Returns the tokenId and expiryDate for a given name, if the name registration has not expired. + * @param _name The name to query for its associated token ID and expiry date. + * @return tokenId The token ID associated with the name. + * @return expiryDate The expiry date of the name registration. + */ + function getName(bytes32 _name) external view returns (uint256 tokenId, uint256 expiryDate); + } ``` @@ -148,7 +157,7 @@ contract NameRegistry is ERC721 { uint256 expiryDate = block.timestamp + duration; _setTokenName(tokenId, _name, expiryDate); - if(oldName != bytes32(0)) { + if (oldName != bytes32(0)) { emit NameChanged(tokenId, oldName, _name, expiryDate); } else { emit TokenNamed(tokenId, _name, expiryDate); @@ -157,6 +166,12 @@ contract NameRegistry is ERC721 { _lastSetNameTime[tokenId] = block.timestamp; } + function getName(bytes32 _name) public view returns (uint256, uint256) { + require(_nameRegistrations[_name].expiryDate > block.timestamp, "NameRegistry: Name expired or does not exist"); + NameRegistration memory registration = _nameRegistrations[_name]; + return (registration.tokenId, registration.expiryDate); + } + function _mint(address to, uint256 tokenId, bytes32 _name, uint256 duration) internal virtual { super._mint(to, tokenId); uint256 expiryDate = block.timestamp + duration; From 4c4c066f51f9a9277093a312da210e5e43f7f2f0 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 12:40:09 +0800 Subject: [PATCH 20/28] change abstract --- ERCS/erc-7644.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 3a1d2563d3..58eaea2a01 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -13,7 +13,7 @@ requires: 721 ## Abstract -This standard enhances [ERC-721](./eip-721.md) by giving each token a unique name and an expiry date, allowing other token holders to claim the name once it expires. +This extension defines an interface that adds a naming mechanism to [ERC-721](./eip-721.md) tokens. It allows each token to have a unique name with a set expiration date. The interface includes functions for assigning, updating, and querying names and their associated tokens, ensuring that names remain unique until they expire. ## Specification From e3383a67e812ee88061439cb4477e15afbeb7300 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Sat, 2 Mar 2024 20:21:20 +0800 Subject: [PATCH 21/28] Fix typo --- ERCS/erc-7644.md | 1 - 1 file changed, 1 deletion(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 58eaea2a01..ebe141c066 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -22,7 +22,6 @@ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "S Implementers of this extension **MUST** have all of the following functions: ```solidity -// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** From ca84e457d90c1de962ee84b5b1411a5c096b8b47 Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Thu, 7 Mar 2024 02:25:16 +0800 Subject: [PATCH 22/28] Update ERCS/erc-7644.md Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> --- ERCS/erc-7644.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index ebe141c066..5d3922900a 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -94,8 +94,6 @@ interface INameRegistry { ## Rationale -Here are a few design decisions and why they were made: - #### Intuitive Token IDs Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the [ERC-721](./eip-721.md) standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. From ee087f349770e8ff3aeb14ce23b8091d2bfa1cb3 Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Thu, 7 Mar 2024 23:40:50 +0800 Subject: [PATCH 23/28] Update erc-7644.md --- ERCS/erc-7644.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 5d3922900a..2a55a69e5e 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -15,6 +15,18 @@ requires: 721 This extension defines an interface that adds a naming mechanism to [ERC-721](./eip-721.md) tokens. It allows each token to have a unique name with a set expiration date. The interface includes functions for assigning, updating, and querying names and their associated tokens, ensuring that names remain unique until they expire. +### Motivation + +As decentralized domain registration methods evolve with the integration of NFTs, we see an opportunity to extend this paradigm to the realm of usernames. By associating token IDs with usernames, we enhance the intuitive identification of entities within decentralized ecosystems. + +This integration serves multiple purposes: + +- **Intuitiveness:** Numeric token IDs lack intuitive identification. By incorporating usernames, token IDs become more representative, improving usability. + +- **Username Economy Exploration:** The registration mechanism opens avenues for exploring the username economy, offering benefits such as identity verification and social interactions. + +- **Synergy with NFTs:** The fusion of usernames with NFTs unlocks synergistic growth, enabling novel applications like authenticated social interactions and personalized digital assets. + ## 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. From d66e2886136b8de2e0374e78779c3b4977589a16 Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Fri, 8 Mar 2024 00:01:14 +0800 Subject: [PATCH 24/28] Update erc-7644.md --- ERCS/erc-7644.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 2a55a69e5e..3136ca53de 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -1,7 +1,7 @@ --- eip: 7644 title: ERC-721 Name Registry Extension -description: Add a time-limited unique naming registry mechanism to ERC-721 tokens. +description: Extend a time-limited unique name to each token within ERC-721, utilizing the name registry for registration and management. author: Chen Liaoyuan (@chenly) discussions-to: https://ethereum-magicians.org/t/erc-7644-erc-721-name-registry-extension/19022 status: Draft From b109f1b4058e97aa669afe214c3d27df86e6f1e7 Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Fri, 8 Mar 2024 00:20:57 +0800 Subject: [PATCH 25/28] Update erc-7644.md --- ERCS/erc-7644.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 3136ca53de..b4a76fbc86 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -13,7 +13,7 @@ requires: 721 ## Abstract -This extension defines an interface that adds a naming mechanism to [ERC-721](./eip-721.md) tokens. It allows each token to have a unique name with a set expiration date. The interface includes functions for assigning, updating, and querying names and their associated tokens, ensuring that names remain unique until they expire. +This extension defines an interface that adds a naming mechanism to [ERC-721](./eip-721.md) tokens. It allows each token to have a unique name with a set expiration date, ensuring uniqueness within the current NFT contract. The interface includes functions for assigning, updating, and querying names and their associated tokens, ensuring that names remain unique until they expire. The entity responsible for setting names depends on the specific use case scenario when utilizing this extension. ### Motivation @@ -43,7 +43,7 @@ pragma solidity ^0.8.0; * enabling the registration, management, and lookup of names * with associated expiry dates tied to specific tokens. */ -interface INameRegistry { +interface IERC7644 /* is IERC721 */ { /** * @dev Emitted when a token is named. * @param tokenId The token ID that is being named. @@ -125,7 +125,7 @@ pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -contract NameRegistry is ERC721 { +contract ERC7644 is ERC721 { event TokenNamed(uint256 indexed tokenId, bytes32 newName, uint256 expiryDate); event TokenMintedWithName(address indexed to, uint256 indexed tokenId, bytes32 name, uint256 expiryDate); event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate); @@ -142,7 +142,7 @@ contract NameRegistry is ERC721 { uint256 public constant MAX_DURATION = 10 * 365 days; uint256 public constant MIN_SET_NAME_INTERVAL = 1 days; - constructor() ERC721("NameRegistry", "NRG") {} + constructor() ERC721("My Token", "MTK") {} function nameOf(uint256 tokenId) public view returns (bytes32) { require(_tokenNames[tokenId] != bytes32(0) && _nameRegistrations[_tokenNames[tokenId]].expiryDate > block.timestamp, "NameRegistry: Name expired or does not exist"); From 6d7f61a0544602286fcbd886f363b7daa8e4ebb4 Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Fri, 8 Mar 2024 00:26:35 +0800 Subject: [PATCH 26/28] Update erc-7644.md --- ERCS/erc-7644.md | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index b4a76fbc86..7fdf6e65ec 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -52,15 +52,6 @@ interface IERC7644 /* is IERC721 */ { */ event TokenNamed(uint256 indexed tokenId, bytes32 newName, uint256 expiryDate); - /** - * @dev Emitted when a token with a name is minted. - * @param to The address of the token recipient. - * @param tokenId The token ID that is minted. - * @param name The name assigned to the newly minted token. - * @param expiryDate The expiry date of the name registration. - */ - event TokenMintedWithName(address indexed to, uint256 indexed tokenId, bytes32 name, uint256 expiryDate); - /** * @dev Emitted when the name of a token is changed. * @param tokenId The token ID whose name is changed. @@ -127,7 +118,6 @@ import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; contract ERC7644 is ERC721 { event TokenNamed(uint256 indexed tokenId, bytes32 newName, uint256 expiryDate); - event TokenMintedWithName(address indexed to, uint256 indexed tokenId, bytes32 name, uint256 expiryDate); event NameChanged(uint256 indexed tokenId, bytes32 oldName, bytes32 newName, uint256 expiryDate); struct NameRegistration { @@ -181,13 +171,6 @@ contract ERC7644 is ERC721 { return (registration.tokenId, registration.expiryDate); } - function _mint(address to, uint256 tokenId, bytes32 _name, uint256 duration) internal virtual { - super._mint(to, tokenId); - uint256 expiryDate = block.timestamp + duration; - _setTokenName(tokenId, _name, expiryDate); - emit TokenMintedWithName(to, tokenId, _name, expiryDate); - } - function _setTokenName(uint256 tokenId, bytes32 _name, uint256 expiryDate) internal { _tokenNames[tokenId] = _name; _nameRegistrations[_name] = NameRegistration(tokenId, expiryDate); From 0e52c25aec48f6b6033c5ea8d6a016fd8257683b Mon Sep 17 00:00:00 2001 From: Liaoyuan Date: Fri, 8 Mar 2024 00:39:00 +0800 Subject: [PATCH 27/28] Update erc-7644.md --- ERCS/erc-7644.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 7fdf6e65ec..971a2d01dc 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -97,13 +97,17 @@ interface IERC7644 /* is IERC721 */ { ## Rationale -#### Intuitive Token IDs +#### Name Expiry -Current token IDs are predominantly numeric, lacking intuitiveness. The extension of the [ERC-721](./eip-721.md) standard to support Named Tokens aims to facilitate the acceptance and use of this standard within the NFT marketplace. By moving beyond mere numbers to include distinctive names, token IDs can more directly reflect the unique identity or value they represent. +By implementing expiration periods for usernames, we introduce several advantages. This mechanism ensures a dynamic environment where unused or outdated usernames can be released, fostering a healthy ecosystem. It encourages turnover of usernames, preventing long-term hoarding and promoting active participation. Users are motivated to manage their username portfolio, renewing valuable names while relinquishing irrelevant ones. Ultimately, this fosters fairness and efficiency, ensuring naming resources are utilized effectively and refreshed to meet evolving needs. -#### Expanding NFT Use Cases +#### Name Uniqueness -By allowing each token to possess a unique name, we unlock new application scenarios in ecosystems built around scarce username resources, such as domain name registration systems. In such scenarios, domain owners can demonstrate ownership directly by holding the corresponding token, thereby broadening the application spectrum and enhancing the value of NFTs. +Enforcing unique usernames is crucial for maintaining a clear and intuitive identification system. It prevents confusion and enables seamless interactions within decentralized ecosystems. Unique usernames enhance discoverability and facilitate trust in transactions and social interactions. This requirement underscores the importance of clarity in decentralized environments, where precise identification is essential for building trust and facilitating efficient interactions. + +#### Name Registration System + +Introducing a registration system for usernames safeguards against abusive behaviors and promotes fair access to naming resources. Reservation and renewal mechanisms prevent monopolization of desirable usernames while enabling legitimate users to secure names of interest. Reservation ensures fair opportunities to claim desired usernames, preventing hoarding and speculative activities. Renewal mechanisms encourage active engagement and investment in the naming ecosystem. Together, these features create a balanced and inclusive environment, fostering a vibrant community of users. ## Backwards Compatibility From 43116b0cf87c407049e4d72b6d0ff44b26131932 Mon Sep 17 00:00:00 2001 From: liaoyuan Date: Tue, 19 Mar 2024 15:02:40 +0800 Subject: [PATCH 28/28] change getName to nameInfo --- ERCS/erc-7644.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-7644.md b/ERCS/erc-7644.md index 971a2d01dc..474524d3c8 100644 --- a/ERCS/erc-7644.md +++ b/ERCS/erc-7644.md @@ -90,7 +90,7 @@ interface IERC7644 /* is IERC721 */ { * @return tokenId The token ID associated with the name. * @return expiryDate The expiry date of the name registration. */ - function getName(bytes32 _name) external view returns (uint256 tokenId, uint256 expiryDate); + function nameInfo(bytes32 _name) external view returns (uint256 tokenId, uint256 expiryDate); } ``` @@ -169,7 +169,7 @@ contract ERC7644 is ERC721 { _lastSetNameTime[tokenId] = block.timestamp; } - function getName(bytes32 _name) public view returns (uint256, uint256) { + function nameInfo(bytes32 _name) public view returns (uint256, uint256) { require(_nameRegistrations[_name].expiryDate > block.timestamp, "NameRegistry: Name expired or does not exist"); NameRegistration memory registration = _nameRegistrations[_name]; return (registration.tokenId, registration.expiryDate);