From d5940549750b946ee2a7eb4664e54839d097bb25 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 21 Jun 2024 18:29:32 +0300 Subject: [PATCH] moved hub-domain contracts to contracts/contracts --- .../hub-contracts/HubDomainsRegistry.sol | 69 +++++++++++++++++++ contracts/hub-contracts/IHubDomains.sol | 11 +++ .../hub-contracts/IHubDomainsRegistry.sol | 9 +++ contracts/hub-contracts/PublicResolver.sol | 20 ++++++ 4 files changed, 109 insertions(+) create mode 100644 contracts/hub-contracts/HubDomainsRegistry.sol create mode 100644 contracts/hub-contracts/IHubDomains.sol create mode 100644 contracts/hub-contracts/IHubDomainsRegistry.sol create mode 100644 contracts/hub-contracts/PublicResolver.sol diff --git a/contracts/hub-contracts/HubDomainsRegistry.sol b/contracts/hub-contracts/HubDomainsRegistry.sol new file mode 100644 index 00000000..05067a80 --- /dev/null +++ b/contracts/hub-contracts/HubDomainsRegistry.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "./IHubDomains.sol"; +import "./IHubDomainsRegistry.sol"; + +contract HubDomainsRegistry is IHubDomains, IHubDomainsRegistry, Ownable { + struct Domain { + string name; + address owner; + string metadataUri; + } + + mapping(string => Domain) private domains; + mapping(address => string[]) private ownerToDomains; + mapping(uint256 => string) private tokenIdToDomain; + uint256 private tokenIdCounter; + + event DomainRegistered(address indexed owner, string domain, uint256 tokenId); + + function registerDomain(string calldata domain, string calldata metadataUri) external override(IHubDomains, IHubDomainsRegistry) { + require(domains[domain].owner == address(0), "Domain already registered"); + require(_isValidDomain(domain), "Invalid domain format"); + + tokenIdCounter++; + domains[domain] = Domain(domain, msg.sender, metadataUri); + ownerToDomains[msg.sender].push(domain); + tokenIdToDomain[tokenIdCounter] = domain; + + emit DomainRegistered(msg.sender, domain, tokenIdCounter); + } + + function resolveDomain(string calldata domain) external view override(IHubDomains, IHubDomainsRegistry) returns (address) { + return domains[domain].owner; + } + + function getDomainMetadata(string calldata domain) external view override(IHubDomains, IHubDomainsRegistry) returns (string memory) { + return domains[domain].metadataUri; + } + + function ownerOf(uint256 tokenId) external view override(IHubDomains, IHubDomainsRegistry) returns (address owner) { + return domains[tokenIdToDomain[tokenId]].owner; + } + + function _isValidDomain(string memory domain) internal pure returns (bool) { + bytes memory b = bytes(domain); + if (b.length == 0 || b.length > 20) return false; // Adjust length as needed + if (!(_endsWithHub(domain))) return false; // Ends with ".hub" + for (uint i; i < b.length - 4; i++) { // Skip ".hub" + if (!(b[i] >= 0x30 && b[i] <= 0x39) && // 0-9 + !(b[i] >= 0x41 && b[i] <= 0x5A) && // A-Z + !(b[i] >= 0x61 && b[i] <= 0x7A)) { // a-z + return false; + } + } + return true; + } + + function _endsWithHub(string memory domain) internal pure returns (bool) { + bytes memory b = bytes(domain); + return b.length >= 4 && + b[b.length - 1] == 'b' && + b[b.length - 2] == 'u' && + b[b.length - 3] == 'h' && + b[b.length - 4] == '.'; + } +} diff --git a/contracts/hub-contracts/IHubDomains.sol b/contracts/hub-contracts/IHubDomains.sol new file mode 100644 index 00000000..e23f2528 --- /dev/null +++ b/contracts/hub-contracts/IHubDomains.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IHubDomains { + event DomainRegistered(address indexed owner, string domain, uint256 tokenId); + + function registerDomain(string calldata domain, string calldata metadataUri) external; + function resolveDomain(string calldata domain) external view returns (address); + function getDomainMetadata(string calldata domain) external view returns (string memory); + function ownerOf(uint256 tokenId) external view returns (address owner); +} diff --git a/contracts/hub-contracts/IHubDomainsRegistry.sol b/contracts/hub-contracts/IHubDomainsRegistry.sol new file mode 100644 index 00000000..09741261 --- /dev/null +++ b/contracts/hub-contracts/IHubDomainsRegistry.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IHubDomainsRegistry { + function registerDomain(string calldata domain, string calldata metadataUri) external; + function resolveDomain(string calldata domain) external view returns (address); + function getDomainMetadata(string calldata domain) external view returns (string memory); + function ownerOf(uint256 tokenId) external view returns (address owner); +} diff --git a/contracts/hub-contracts/PublicResolver.sol b/contracts/hub-contracts/PublicResolver.sol new file mode 100644 index 00000000..80e413cf --- /dev/null +++ b/contracts/hub-contracts/PublicResolver.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "./HubDomainsRegistry.sol"; + +contract PublicResolver { + HubDomainsRegistry public hubDomainsRegistry; + + constructor(address _hubDomainsRegistry) { + hubDomainsRegistry = HubDomainsRegistry(_hubDomainsRegistry); + } + + function resolveDomain(string calldata domain) external view returns (address) { + return hubDomainsRegistry.resolveDomain(domain); + } + + function getDomainMetadata(string calldata domain) external view returns (string memory) { + return hubDomainsRegistry.getDomainMetadata(domain); + } +}