diff --git a/contracts/src/registry/RootRegistry.sol b/contracts/src/registry/RootRegistry.sol index 07ece49..602b9c1 100644 --- a/contracts/src/registry/RootRegistry.sol +++ b/contracts/src/registry/RootRegistry.sol @@ -13,12 +13,14 @@ import {BaseRegistry} from "./BaseRegistry.sol"; contract RootRegistry is LockableRegistry, AccessControl { bytes32 public constant TLD_ISSUER_ROLE = keccak256("TLD_ISSUER_ROLE"); + mapping(uint256 tokenId=>string) uris; + constructor(IRegistryDatastore _datastore) LockableRegistry(_datastore) { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } - function uri(uint256 /*id*/ ) public pure override returns (string memory) { - return ""; + function uri(uint256 tokenId ) public view override returns (string memory) { + return uris[tokenId]; } /** @@ -27,8 +29,9 @@ contract RootRegistry is LockableRegistry, AccessControl { * @param owner The new owner of the TLD token. * @param registry The address of the registry to use. * @param flags Flags to set. + * @param _uri URI for TLD metadata. */ - function mint(string calldata label, address owner, IRegistry registry, uint96 flags) + function mint(string calldata label, address owner, IRegistry registry, uint96 flags, string memory _uri) external onlyRole(TLD_ISSUER_ROLE) returns(uint256 tokenId) @@ -36,6 +39,8 @@ contract RootRegistry is LockableRegistry, AccessControl { tokenId = uint256(keccak256(bytes(label))); _mint(owner, tokenId, 1, ""); datastore.setSubregistry(tokenId, address(registry), flags); + uris[tokenId] = _uri; + emit URI(_uri, tokenId); emit NewSubname(label); } @@ -62,6 +67,14 @@ contract RootRegistry is LockableRegistry, AccessControl { return _lock(tokenId, flags); } + function setUri(uint256 tokenId, string memory _uri) + external + onlyTokenOwner(tokenId) + { + emit URI(_uri, tokenId); + uris[tokenId] = _uri; + } + function supportsInterface(bytes4 interfaceId) public view override(BaseRegistry, AccessControl) returns (bool) { return super.supportsInterface(interfaceId); } diff --git a/contracts/test/RootRegistry.t.sol b/contracts/test/RootRegistry.t.sol index c6edad7..f33eaa7 100644 --- a/contracts/test/RootRegistry.t.sol +++ b/contracts/test/RootRegistry.t.sol @@ -26,7 +26,7 @@ contract TestRootRegistry is Test, ERC1155Holder { vm.expectEmit(true, true, true, true); emit TransferSingle(address(this), address(0), address(this), expectedId, 1); - uint256 tokenId = registry.mint("test2", address(this), registry, 0); + uint256 tokenId = registry.mint("test2", address(this), registry, 0, ""); vm.assertEq(tokenId, expectedId); uint96 flags = registry.flags(tokenId); vm.assertEq(flags, 0); @@ -38,7 +38,7 @@ contract TestRootRegistry is Test, ERC1155Holder { vm.expectEmit(true, true, true, true); emit TransferSingle(address(this), address(0), address(this), expectedId, 1); - uint256 tokenId = registry.mint("test2", address(this), registry, flags); + uint256 tokenId = registry.mint("test2", address(this), registry, flags, ""); vm.assertEq(tokenId, expectedId); uint96 actualFlags = registry.flags(tokenId); vm.assertEq(flags, actualFlags); @@ -46,7 +46,7 @@ contract TestRootRegistry is Test, ERC1155Holder { function test_lock_name() public { uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); - uint256 tokenId = registry.mint("test2", address(this), registry, 0); + uint256 tokenId = registry.mint("test2", address(this), registry, 0, ""); uint96 actualFlags = registry.lock(tokenId, flags); vm.assertEq(flags, actualFlags); uint96 actualFlags2 = registry.flags(tokenId); @@ -56,7 +56,7 @@ contract TestRootRegistry is Test, ERC1155Holder { function test_cannot_unlock_name() public { uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); - uint256 tokenId = registry.mint("test2", address(this), registry, flags); + uint256 tokenId = registry.mint("test2", address(this), registry, flags, ""); uint96 newFlags = registry.lock(tokenId, 0); vm.assertEq(flags, newFlags); uint96 newFlags2 = registry.flags(tokenId); @@ -64,32 +64,54 @@ contract TestRootRegistry is Test, ERC1155Holder { } function test_set_subregistry() public { - uint256 tokenId = registry.mint("test", address(this), registry, 0); + uint256 tokenId = registry.mint("test", address(this), registry, 0, ""); registry.setSubregistry(tokenId, IRegistry(address(this))); vm.assertEq(address(registry.getSubregistry("test")), address(this)); } function testFail_cannot_set_locked_subregistry() public { uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED(); - uint256 tokenId = registry.mint("test", address(this), registry, flags); + uint256 tokenId = registry.mint("test", address(this), registry, flags, ""); registry.setSubregistry(tokenId, IRegistry(address(this))); } function test_set_resolver() public { - uint256 tokenId = registry.mint("test", address(this), registry, 0); + uint256 tokenId = registry.mint("test", address(this), registry, 0, ""); registry.setResolver(tokenId, address(this)); vm.assertEq(address(registry.getResolver("test")), address(this)); } function testFail_cannot_set_locked_resolver() public { uint96 flags = registry.FLAG_RESOLVER_LOCKED(); - uint256 tokenId = registry.mint("test", address(this), registry, flags); + uint256 tokenId = registry.mint("test", address(this), registry, flags, ""); registry.setResolver(tokenId, address(this)); } function testFail_cannot_set_locked_flags() public { uint96 flags = registry.FLAG_FLAGS_LOCKED(); - uint256 tokenId = registry.mint("test", address(this), registry, flags); + uint256 tokenId = registry.mint("test", address(this), registry, flags, ""); registry.lock(tokenId, registry.FLAG_RESOLVER_LOCKED()); } + + function test_set_uri() public { + string memory uri = "https://example.com/"; + uint256 tokenId = registry.mint("test2", address(this), registry, 0, uri); + string memory actualUri = registry.uri(tokenId); + vm.assertEq(actualUri, uri); + + uri = "https://ens.domains/"; + registry.setUri(tokenId, uri); + actualUri = registry.uri(tokenId); + vm.assertEq(actualUri, uri); + } + + function testFail_cannot_set_unauthorized_uri() public { + string memory uri = "https://example.com/"; + uint256 tokenId = registry.mint("test2", address(registry), registry, 0, uri); + string memory actualUri = registry.uri(tokenId); + vm.assertEq(actualUri, uri); + + uri = "https://ens.domains/"; + registry.setUri(tokenId, uri); + } } diff --git a/contracts/test/fixtures/deployEnsFixture.ts b/contracts/test/fixtures/deployEnsFixture.ts index 3ba86da..28247b6 100644 --- a/contracts/test/fixtures/deployEnsFixture.ts +++ b/contracts/test/fixtures/deployEnsFixture.ts @@ -31,6 +31,7 @@ export async function deployEnsFixture() { accounts[0].address, ethRegistry.address, 1n, + "https://example.com/" ]); return {