{"id":20415748,"url":"https://github.com/unstoppabledomains/uns","last_synced_at":"2025-04-05T01:05:58.891Z","repository":{"id":37888433,"uuid":"360102831","full_name":"unstoppabledomains/uns","owner":"unstoppabledomains","description":"UNS (Unstoppable Naming Service)","archived":false,"fork":false,"pushed_at":"2025-03-28T15:16:27.000Z","size":77710,"stargazers_count":91,"open_issues_count":10,"forks_count":42,"subscribers_count":19,"default_branch":"main","last_synced_at":"2025-03-28T16:23:07.759Z","etag":null,"topics":["blockchain","cns","custody","ens","ethereum","polygon","solidity","uns"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unstoppabledomains.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-04-21T09:08:40.000Z","updated_at":"2025-03-17T22:47:03.000Z","dependencies_parsed_at":"2024-01-22T22:09:25.004Z","dependency_job_id":"467f96f8-7bb2-469c-a60d-12ac53505568","html_url":"https://github.com/unstoppabledomains/uns","commit_stats":null,"previous_names":[],"tags_count":176,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unstoppabledomains%2Funs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unstoppabledomains%2Funs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unstoppabledomains%2Funs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unstoppabledomains%2Funs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unstoppabledomains","download_url":"https://codeload.github.com/unstoppabledomains/uns/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271528,"owners_count":20911587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","cns","custody","ens","ethereum","polygon","solidity","uns"],"created_at":"2024-11-15T06:17:25.248Z","updated_at":"2025-04-05T01:05:58.871Z","avatar_url":"https://github.com/unstoppabledomains.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UNS (Unstoppable Naming Service)\n\nUNS Registry smart contracts.\nAuthor: Unstoppable Domains, Inc., 2021. All rights reserved.\n\n## Official deployments\n\nUNS Contracts are officially deployed to several different Ethereum and Polygon networks\nThe contract addresses are distributed via a [UNS Config File](https://github.com/unstoppabledomains/uns/blob/main/uns-config.json) and always kept up to date.\n\n\n## Specifications\n\n1. Implements ERC721\n\n    [ERC-721](https://eips.ethereum.org/EIPS/eip-721) Non-Fungible Token Standard\n\n2. Implements ERC165\n\n    [ERC-165](https://eips.ethereum.org/EIPS/eip-165) Standard Interface Detection\n\n3. Implements IERC721Metadata\n\n    \u003e IERC721Metadata is an extension of ERC-721. IERC721Metadata allows smart contract to be interrogated for its name and for details about the assets which your NFTs represent.\n\n    Ref: https://eips.ethereum.org/EIPS/eip-721\n\n4. Implements [IUNSRegistry](./contracts/IUNSRegistry.sol)\n\n5. Record Storage (aka Resolver)\n\n    Record Storage implements [IRecordStorage](./contracts/IRecordStorage.sol)\n\n6. Support meta-transactions\n\n    [EIP-2771](https://eips.ethereum.org/EIPS/eip-2771): Secure Protocol for Native Meta Transactions\n\n    ### Recipient:\n\n    In order to support `EIP-2771` recipient should implement `Context`.\n\n    ```solidity\n    interface Context {\n        function _msgSender() internal view returns (address);\n        function _msgData() internal view returns (bytes calldata);\n    }\n    ```\n\n    The implementation should allow replacement of `_msgSender` and `_msgData` in case of forwarding.\n\n    Implementation [ERC2771RegistryContext.sol](./contracts/metatx/ERC2771RegistryContext.sol)\n\n    ### Forwarder:\n\n    ```solidity\n    struct ForwardRequest {\n        address from;\n        uint256 tokenId;\n        uint256 nonce;\n        bytes data;\n    }\n\n    interface Forwarder {\n        /**\n         * @dev Return current token nonce\n         */\n        function nonceOf(uint256 tokenId) public view returns (uint256);\n\n        /**\n         * @dev Verify signature against provided request\n         */\n        function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool);\n\n        /**\n         * @dev Execute bytecode if signature is correct\n         */\n        function execute(ForwardRequest calldata req, bytes calldata signature) public returns (bool, bytes memory);\n    }\n    ```\n\n    Implementation [UNSRegistryForwarder.sol](./contracts/metatx/UNSRegistryForwarder.sol)\n\n7. Upgradability\n\n    \u003e By design, smart contracts are immutable. On the other hand, software quality heavily depends on the ability to upgrade and patch source code in order to produce iterative releases. Even though blockchain based software profits significantly from the technology’s immutability, still a certain degree of mutability is needed for bug fixing and potential product improvements.\n\n    Upgradability comes from two patterns:\n    1. Initializable\n        \u003e Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n        external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n        function so it can only be called once.\n    2. Context\n        \u003e Provides information about the current execution context, including the\n        sender of the transaction and its data.\n\n    UNS uses [Transparent Proxy](https://blog.openzeppelin.com/the-transparent-proxy-pattern/) for upgradability.\n\n    Refs:\n\n    - [IMPORTANT: Storage layout](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#modifying-your-contracts)\n    - [Writing Upgradeable Contracts](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable)\n    - [UUPS Proxies: Tutorial (Solidity + JavaScript)](https://forum.openzeppelin.com/t/uups-proxies-tutorial-solidity-javascript/7786)\n    - [Transparent vs UUPS Proxies](https://docs.openzeppelin.com/contracts/4.x/api/proxy#transparent-vs-uups)\n\n8. TLD management\n\n    UNS TLD management is delegated to MintingManager contract.\n\n    ```solidity\n    contract IMintingManager {\n        /**\n         * @dev Mapping TLD `hashname` to TLD label\n         *\n         * `hashname` = uint256(keccak256(abi.encodePacked(uint256(0x0), keccak256(abi.encodePacked(label)))))\n         */\n        mapping(uint256 =\u003e string) internal _tlds;\n    }\n    ```\n\n9. Domain minting\n\n    **Unstoppable Domains, Inc.** reserves all rights of domains minting and defines rules of domain minting through MintingManager contract.\n\n10. Roles model\n\n    TBD\n\n## Development\n\nIn order to compile, use `yarn compile`, this also autogenerates [typechain](https://github.com/dethcrypto/TypeChain) types.\nAlso, please note that in tests, it's required to use factories and types, generated by `typechain`. For example:\n\n```typescript\nimport { UNSRegistry } from '../types/contracts';\nimport { UNSRegistry__factory } from '../types/factories/contracts';\n\n\ndescribe('UNSRegistry', () =\u003e {\n  let unsRegistry: UNSRegistry;\n\n  let coinbase: SignerWithAddress;\n\n  before(async () =\u003e {\n    [coinbase] = await ethers.getSigners();\n\n    unsRegistry = await new UNSRegistry__factory(coinbase).deploy();\n  });\n\n  it('test', () =\u003e {\n    // ...\n  });\n});\n```\n\n## Dependencies\n\n- [Slither](https://github.com/crytic/slither) - solidity source analyzer [optional]\n\n  Installation command: `pip3 install slither-analyzer`\n\n## Environment variables\n\n- `{NETWORK}_INFURA_KEY` - Infura key for connecting to Ethereum Node\n- `{NETWORK}_UNS_PRIVATE_KEY` - Private key of account for contracts deployment\n- `{EXPLORER}_API_KEY` - Etherscan(or any whitelabled compatible explorer) API Key for smart contracts verification\n\nNOTE: All private keys should be in HEX format with `0x` prefix\n\nNetwork | Variables\n--- | ---\nMainnet | MAINNET_INFURA_KEY \u003cbr /\u003e MAINNET_UNS_PRIVATE_KEY \u003cbr /\u003e ETHERSCAN_API_KEY\nSepolia | SEPOLIA_INFURA_KEY \u003cbr /\u003e SEPOLIA_UNS_PRIVATE_KEY \u003cbr /\u003e ETHERSCAN_API_KEY\nPolygon | POLYGON_INFURA_KEY \u003cbr /\u003e POLYGON_UNS_PRIVATE_KEY \u003cbr /\u003e POLYGONSCAN_API_KEY\nAmoy | AMOY_INFURA_KEY \u003cbr /\u003e AMOY_UNS_PRIVATE_KEY \u003cbr /\u003e POLYGONSCAN_API_KEY\nBase | BASE_INFURA_KEY \u003cbr /\u003e BASE_UNS_PRIVATE_KEY \u003cbr /\u003e BASESCAN_API_KEY\nBase sepolia | BASE_INFURA_KEY \u003cbr /\u003e BASE_UNS_PRIVATE_KEY \u003cbr /\u003e BASESCAN_API_KEY\n\n\u003cdiv id=\"backward-incompatibility\"\u003e\u003c/div\u003e\n\n## Backward incompatibility\n\nNote: List of changes which makes UNS and CNS backward incompatible\n\n### Events\n\n* `event Approved ApprovedForAll Transfer NewURI`\n  * Unchanged\n* `event Resolve(uint256 indexed tokenId, address indexed to)` \n  * Removed\n  * UNS has a single resolver which is Registry, so one can assume that resolver is always set to registry address\n* `event Sync(address indexed resolver, uint256 indexed updateId, uint256 indexed tokenId)` \n  * Removed\n  * There is no need for this event because there is only one resolver and changes can be tracked by `Set` event instead\n* `event Set(uint256 indexed tokenId, string indexed keyIndex, string indexed valueIndex, string key, string value)` \n  * Moved from Resolver to Registry\n* `event NewKey(uint256 indexed tokenId, string indexed keyIndex, string key)` \n  * Moved from Resolver to Regisry\n* `event ResetRecords(uint256 indexed tokenId)` \n  * Moved from Resolver to Registry\n  * Registry now fires this event when records are reset on transfer.\n\n### Resolvers Removal\n\n* `function resolveTo(address to, uint256 tokenId) external {}` \n  * Removed - UNS uses a single Resolver which is Registry itself.\n* `function resolverOf(uint256 tokenId)`\n  * Now always returns Registry address itself\n\n---\n## Sandbox\n\n[\u003e\u003e README](./sandbox/README.md)\n\n## Deploying contracts\n\nScripts for deploying contracts are located inside `./scripts` directory. In order to run them, you can use\nthe following command:\n\n```\nyarn hardhat run --network \u003cnetwork\u003e scripts/filename.ts\n```\n\nAs scripts make JSON-RPC calls to Infura and sign transactions, you'll need to specify 2 environment variables.\nThose variables' names depend on the network you want deploy the contracts to. Assuming you want to deploy new contracts\nto Sepolia, you'll need the following variables:\n\n```\nexport SEPOLIA_UNS_PRIVATE_KEY=\u003cHEX_PRIVATE_KEY\u003e\nexport SEPOLIA_INFURA_KEY=\u003cINFURA_PROJECT_ID\u003e\n```\n\nThe scripts located in `./scripts` directory are wrappers around Deployer tasks. You can see their definitions inside\n`src/tasks.ts`.\n\n### Deploying CNS\n\n```\nyarn hardhat run --network \u003cnetwork\u003e scripts/deploy_CNS.ts\n```\n\n### Deploying UNS\n\nUNS depends on CNS, as CNS registry address is used as a MintingManager's initializer argument. Before deploying UNS,\nmake sure that CNS is deployed and actual CNS contract addresses are specified in the `uns-config.json` file.\n\n```\nyarn hardhat run --network \u003cnetwork\u003e scripts/deploy.ts\n```\n\nWarning: In case of contracts' redeployment, make sure there is no deployment output file `.deployer/{chain_id}.json`\n\n### Deploying UNS on L2(Polygon/Amoy)\n```\nyarn hardhat run --network amoy scripts/deploy_UNS_only.ts\n```\n\n## L2 Polygon\nThere are configs networks [Mainnet](https://static.polygon.technology/network/mainnet/v1/index.json), [Testnet](https://static.polygon.technology/network/testnet/amoy/index.json)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funstoppabledomains%2Funs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funstoppabledomains%2Funs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funstoppabledomains%2Funs/lists"}