From 73eb5ab5384ece46108327d9cf276e86e6065954 Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Wed, 28 Aug 2024 13:48:26 +0100 Subject: [PATCH 1/3] Refactor locking functionality into LockableRegistry --- contracts/src/registry/BaseRegistry.sol | 5 --- contracts/src/registry/ETHRegistry.sol | 48 +++++--------------- contracts/src/registry/LockableRegistry.sol | 50 +++++++++++++++++++++ contracts/src/registry/RootRegistry.sol | 46 +++++++++---------- contracts/src/registry/UserRegistry.sol | 3 +- contracts/test/ETHRegistry.t.sol | 8 ++-- 6 files changed, 90 insertions(+), 70 deletions(-) create mode 100644 contracts/src/registry/LockableRegistry.sol diff --git a/contracts/src/registry/BaseRegistry.sol b/contracts/src/registry/BaseRegistry.sol index aa904de..1acbbf1 100644 --- a/contracts/src/registry/BaseRegistry.sol +++ b/contracts/src/registry/BaseRegistry.sol @@ -62,11 +62,6 @@ abstract contract BaseRegistry is IRegistry, ERC1155Singleton { || interfaceId == type(IRegistry).interfaceId || super.supportsInterface(interfaceId); } - function _mint(uint256 tokenId, address owner, IRegistry registry, uint96 flags) internal { - _mint(owner, tokenId, 1, ""); - datastore.setSubregistry(tokenId, address(registry), flags); - } - /** * * IRegistry functions * diff --git a/contracts/src/registry/ETHRegistry.sol b/contracts/src/registry/ETHRegistry.sol index 17b897d..cd2448b 100644 --- a/contracts/src/registry/ETHRegistry.sol +++ b/contracts/src/registry/ETHRegistry.sol @@ -8,19 +8,16 @@ import {IERC1155Singleton} from "./IERC1155Singleton.sol"; import {IRegistry} from "./IRegistry.sol"; import {IRegistryDatastore} from "./IRegistryDatastore.sol"; import {BaseRegistry} from "./BaseRegistry.sol"; +import {LockableRegistry} from "./LockableRegistry.sol"; -contract ETHRegistry is BaseRegistry, AccessControl { +contract ETHRegistry is LockableRegistry, AccessControl { bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); - uint32 public constant FLAGS_MASK = 0x7; - uint32 public constant FLAG_SUBREGISTRY_LOCKED = 0x1; - uint32 public constant FLAG_RESOLVER_LOCKED = 0x2; - uint32 public constant FLAG_FLAGS_LOCKED = 0x4; error NameAlreadyRegistered(string label); error NameExpired(uint256 tokenId); error CannotReduceExpiration(uint64 oldExpiration, uint64 newExpiration); - constructor(IRegistryDatastore _datastore) BaseRegistry(_datastore) { + constructor(IRegistryDatastore _datastore) LockableRegistry(_datastore) { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } @@ -43,13 +40,13 @@ contract ETHRegistry is BaseRegistry, AccessControl { return super.ownerOf(tokenId); } - function register(string calldata label, address owner, IRegistry registry, uint32 flags, uint64 expires) + function register(string calldata label, address owner, IRegistry registry, uint96 flags, uint64 expires) public onlyRole(REGISTRAR_ROLE) returns (uint256 tokenId) { - flags &= FLAGS_MASK; tokenId = (uint256(keccak256(bytes(label))) & ~uint256(FLAGS_MASK)) | flags; + flags = (flags & FLAGS_MASK) | (uint96(expires) << 32); (, uint96 oldFlags) = datastore.getSubregistry(tokenId); uint64 oldExpiry = uint64(oldFlags >> 32); @@ -57,7 +54,8 @@ contract ETHRegistry is BaseRegistry, AccessControl { revert NameAlreadyRegistered(label); } - _mint(tokenId, owner, registry, uint96(flags) | (uint96(expires) << 32)); + _mint(owner, tokenId, 1, ""); + datastore.setSubregistry(tokenId, address(registry), flags); emit NewSubname(label); return tokenId; } @@ -79,42 +77,20 @@ contract ETHRegistry is BaseRegistry, AccessControl { return (uint64(_flags >> 32), uint32(_flags)); } - function lock(uint256 tokenId, uint32 flags) + function lock(uint256 tokenId, uint96 flags) external onlyTokenOwner(tokenId) - withSubregistryFlags(tokenId, FLAG_FLAGS_LOCKED, 0) returns (uint256 newTokenId) { - (address subregistry, uint96 oldFlags) = datastore.getSubregistry(tokenId); - uint96 newFlags = oldFlags | (flags & FLAGS_MASK); - if (newFlags != oldFlags) { + uint96 newFlags = _lock(tokenId, flags); + newTokenId = (tokenId & ~uint256(FLAGS_MASK)) | (newFlags & FLAGS_MASK); + if (tokenId != newTokenId) { address owner = ownerOf(tokenId); _burn(owner, tokenId, 1); - newTokenId = (tokenId & ~uint256(FLAGS_MASK)) | (newFlags & FLAGS_MASK); - _mint(newTokenId, owner, IRegistry(subregistry), newFlags); - } else { - newTokenId = tokenId; + _mint(owner, newTokenId, 1, ""); } } - function setSubregistry(uint256 tokenId, IRegistry registry) - external - onlyTokenOwner(tokenId) - withSubregistryFlags(tokenId, FLAG_SUBREGISTRY_LOCKED, 0) - { - (, uint96 flags) = datastore.getSubregistry(tokenId); - datastore.setSubregistry(tokenId, address(registry), flags); - } - - function setResolver(uint256 tokenId, address resolver) - external - onlyTokenOwner(tokenId) - withSubregistryFlags(tokenId, FLAG_RESOLVER_LOCKED, 0) - { - (, uint96 flags) = datastore.getResolver(tokenId); - datastore.setResolver(tokenId, resolver, flags); - } - function supportsInterface(bytes4 interfaceId) public view override(BaseRegistry, AccessControl) returns (bool) { return interfaceId == type(IRegistry).interfaceId || super.supportsInterface(interfaceId); } diff --git a/contracts/src/registry/LockableRegistry.sol b/contracts/src/registry/LockableRegistry.sol new file mode 100644 index 0000000..1c5e509 --- /dev/null +++ b/contracts/src/registry/LockableRegistry.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; + +import {ERC1155Singleton} from "./ERC1155Singleton.sol"; +import {IERC1155Singleton} from "./IERC1155Singleton.sol"; +import {IRegistry} from "./IRegistry.sol"; +import {IRegistryDatastore} from "./IRegistryDatastore.sol"; +import {BaseRegistry} from "./BaseRegistry.sol"; + +abstract contract LockableRegistry is BaseRegistry { + uint96 public constant FLAGS_MASK = 0x7; + uint96 public constant FLAG_SUBREGISTRY_LOCKED = 0x1; + uint96 public constant FLAG_RESOLVER_LOCKED = 0x2; + uint96 public constant FLAG_FLAGS_LOCKED = 0x4; + + constructor(IRegistryDatastore _datastore) BaseRegistry(_datastore) { + } + + function _lock(uint256 tokenId, uint96 flags) + internal + withSubregistryFlags(tokenId, FLAG_FLAGS_LOCKED, 0) + returns(uint96 newFlags) + { + (address subregistry, uint96 oldFlags) = datastore.getSubregistry(tokenId); + newFlags = oldFlags | (flags & FLAGS_MASK); + if (newFlags != oldFlags) { + datastore.setSubregistry(tokenId, subregistry, newFlags); + } + } + + function setSubregistry(uint256 tokenId, IRegistry registry) + external + onlyTokenOwner(tokenId) + withSubregistryFlags(tokenId, FLAG_SUBREGISTRY_LOCKED, 0) + { + (, uint96 flags) = datastore.getSubregistry(tokenId); + datastore.setSubregistry(tokenId, address(registry), flags); + } + + function setResolver(uint256 tokenId, address resolver) + external + onlyTokenOwner(tokenId) + withSubregistryFlags(tokenId, FLAG_RESOLVER_LOCKED, 0) + { + (, uint96 flags) = datastore.getResolver(tokenId); + datastore.setResolver(tokenId, resolver, flags); + } +} diff --git a/contracts/src/registry/RootRegistry.sol b/contracts/src/registry/RootRegistry.sol index 6f03995..3414aa9 100644 --- a/contracts/src/registry/RootRegistry.sol +++ b/contracts/src/registry/RootRegistry.sol @@ -7,14 +7,13 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IRegistry} from "./IRegistry.sol"; import {IRegistryDatastore} from "./IRegistryDatastore.sol"; +import {LockableRegistry} from "./LockableRegistry.sol"; import {BaseRegistry} from "./BaseRegistry.sol"; -contract RootRegistry is BaseRegistry, AccessControl { - bytes32 public constant SUBDOMAIN_ISSUER_ROLE = keccak256("SUBDOMAIN_ISSUER_ROLE"); - uint96 public constant SUBREGISTRY_FLAGS_MASK = 0x1; - uint96 public constant SUBREGISTRY_FLAG_LOCKED = 0x1; +contract RootRegistry is LockableRegistry, AccessControl { + bytes32 public constant TLD_ISSUER_ROLE = keccak256("TLD_ISSUER_ROLE"); - constructor(IRegistryDatastore _datastore) BaseRegistry(_datastore) { + constructor(IRegistryDatastore _datastore) LockableRegistry(_datastore) { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } @@ -22,39 +21,38 @@ contract RootRegistry is BaseRegistry, AccessControl { return ""; } - function mint(string calldata label, address owner, IRegistry registry, bool locked) + /** + * @dev Mints a new TLD. + * @param label The plaintext label for the TLD. + * @param owner The new owner of the TLD token. + * @param registry The address of the registry to use. + * @param flags Flags to set. + */ + function mint(string calldata label, address owner, IRegistry registry, uint32 flags) external - onlyRole(SUBDOMAIN_ISSUER_ROLE) + onlyRole(TLD_ISSUER_ROLE) { uint256 tokenId = uint256(keccak256(bytes(label))); - _mint(tokenId, owner, registry, locked ? SUBREGISTRY_FLAG_LOCKED : 0); + _mint(owner, tokenId, 1, ""); + datastore.setSubregistry(tokenId, address(registry), flags); emit NewSubname(label); } + /** + * @dev Burns a TLD. + * TLDs cannot be burned if any of their flags are set. + * @param tokenId The tokenID of the TLD to burn. + */ function burn(uint256 tokenId) external - onlyRole(SUBDOMAIN_ISSUER_ROLE) - withSubregistryFlags(tokenId, SUBREGISTRY_FLAGS_MASK, 0) + onlyTokenOwner(tokenId) + withSubregistryFlags(tokenId, FLAGS_MASK, 0) { address owner = ownerOf(tokenId); _burn(owner, tokenId, 1); datastore.setSubregistry(tokenId, address(0), 0); } - function lock(uint256 tokenId) external onlyRole(SUBDOMAIN_ISSUER_ROLE) { - (address subregistry, uint96 flags) = datastore.getSubregistry(tokenId); - datastore.setSubregistry(tokenId, subregistry, flags & SUBREGISTRY_FLAG_LOCKED); - } - - function setSubregistry(uint256 tokenId, IRegistry registry) - external - onlyTokenOwner(tokenId) - withSubregistryFlags(tokenId, SUBREGISTRY_FLAGS_MASK, 0) - { - (, uint96 flags) = datastore.getSubregistry(tokenId); - datastore.setSubregistry(tokenId, address(registry), flags); - } - function supportsInterface(bytes4 interfaceId) public view override(BaseRegistry, AccessControl) returns (bool) { return super.supportsInterface(interfaceId); } diff --git a/contracts/src/registry/UserRegistry.sol b/contracts/src/registry/UserRegistry.sol index 0922f9a..f34e8c8 100644 --- a/contracts/src/registry/UserRegistry.sol +++ b/contracts/src/registry/UserRegistry.sol @@ -36,7 +36,8 @@ contract UserRegistry is BaseRegistry { function mint(string calldata _label, address owner, IRegistry registry, uint96 flags) external onlyNameOwner { uint256 tokenId = uint256(keccak256(bytes(_label))); - _mint(tokenId, owner, registry, flags); + _mint(owner, tokenId, 1, ""); + datastore.setSubregistry(tokenId, address(registry), flags); emit NewSubname(label); } diff --git a/contracts/test/ETHRegistry.t.sol b/contracts/test/ETHRegistry.t.sol index b8ec19d..86f95b0 100644 --- a/contracts/test/ETHRegistry.t.sol +++ b/contracts/test/ETHRegistry.t.sol @@ -32,7 +32,7 @@ contract TestETHRegistry is Test, ERC1155Holder { } function test_register_locked() public { - uint32 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); uint256 expectedId = uint256(keccak256("test2") & 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8) | flags; vm.expectEmit(true, true, true, true); @@ -43,7 +43,7 @@ contract TestETHRegistry is Test, ERC1155Holder { } function test_lock_name() public { - uint32 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); uint256 oldTokenId = registry.register("test2", address(this), registry, 0, uint64(block.timestamp) + 86400); vm.expectEmit(true, true, true, true); @@ -57,7 +57,7 @@ contract TestETHRegistry is Test, ERC1155Holder { } function test_cannot_unlock_name() public { - uint32 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); uint256 oldTokenId = registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); uint256 newTokenId = registry.lock(oldTokenId, 0); @@ -65,7 +65,7 @@ contract TestETHRegistry is Test, ERC1155Holder { } function testFail_cannot_mint_duplicates() public { - uint32 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); registry.register("test2", address(this), registry, 0, uint64(block.timestamp) + 86400); From 84508d7b1de21584a57545aee613ce22d0ece394 Mon Sep 17 00:00:00 2001 From: Nick Johnson Date: Wed, 28 Aug 2024 14:42:46 +0100 Subject: [PATCH 2/3] More tests for RootRegistry and ETHRegistry. --- contracts/src/registry/ETHRegistry.sol | 8 +- contracts/src/registry/LockableRegistry.sol | 17 ++-- contracts/src/registry/RootRegistry.sol | 13 ++- contracts/test/ETHRegistry.t.sol | 30 +++++++ contracts/test/RootRegistry.t.sol | 95 +++++++++++++++++++++ 5 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 contracts/test/RootRegistry.t.sol diff --git a/contracts/src/registry/ETHRegistry.sol b/contracts/src/registry/ETHRegistry.sol index cd2448b..c723ae3 100644 --- a/contracts/src/registry/ETHRegistry.sol +++ b/contracts/src/registry/ETHRegistry.sol @@ -98,18 +98,20 @@ contract ETHRegistry is LockableRegistry, AccessControl { function getSubregistry(string calldata label) external view virtual override returns (IRegistry) { (address subregistry, uint96 flags) = datastore.getSubregistry(uint256(keccak256(bytes(label)))); uint64 expires = uint64(flags); - if (expires >= block.timestamp) { + if (expires <= block.timestamp) { return IRegistry(address(0)); } return IRegistry(subregistry); } function getResolver(string calldata label) external view virtual override returns (address) { - (address resolver, uint96 flags) = datastore.getResolver(uint256(keccak256(bytes(label)))); + (address subregistry, uint96 flags) = datastore.getSubregistry(uint256(keccak256(bytes(label)))); uint64 expires = uint64(flags); - if (expires >= block.timestamp) { + if (expires <= block.timestamp) { return address(0); } + + (address resolver, ) = datastore.getResolver(uint256(keccak256(bytes(label)))); return resolver; } } diff --git a/contracts/src/registry/LockableRegistry.sol b/contracts/src/registry/LockableRegistry.sol index 1c5e509..07d6a64 100644 --- a/contracts/src/registry/LockableRegistry.sol +++ b/contracts/src/registry/LockableRegistry.sol @@ -18,13 +18,13 @@ abstract contract LockableRegistry is BaseRegistry { constructor(IRegistryDatastore _datastore) BaseRegistry(_datastore) { } - function _lock(uint256 tokenId, uint96 flags) + function _lock(uint256 tokenId, uint96 _flags) internal withSubregistryFlags(tokenId, FLAG_FLAGS_LOCKED, 0) returns(uint96 newFlags) { (address subregistry, uint96 oldFlags) = datastore.getSubregistry(tokenId); - newFlags = oldFlags | (flags & FLAGS_MASK); + newFlags = oldFlags | (_flags & FLAGS_MASK); if (newFlags != oldFlags) { datastore.setSubregistry(tokenId, subregistry, newFlags); } @@ -35,8 +35,8 @@ abstract contract LockableRegistry is BaseRegistry { onlyTokenOwner(tokenId) withSubregistryFlags(tokenId, FLAG_SUBREGISTRY_LOCKED, 0) { - (, uint96 flags) = datastore.getSubregistry(tokenId); - datastore.setSubregistry(tokenId, address(registry), flags); + (, uint96 _flags) = datastore.getSubregistry(tokenId); + datastore.setSubregistry(tokenId, address(registry), _flags); } function setResolver(uint256 tokenId, address resolver) @@ -44,7 +44,12 @@ abstract contract LockableRegistry is BaseRegistry { onlyTokenOwner(tokenId) withSubregistryFlags(tokenId, FLAG_RESOLVER_LOCKED, 0) { - (, uint96 flags) = datastore.getResolver(tokenId); - datastore.setResolver(tokenId, resolver, flags); + (, uint96 _flags) = datastore.getResolver(tokenId); + datastore.setResolver(tokenId, resolver, _flags); + } + + function flags(uint256 tokenId) external view returns(uint96) { + (, uint96 _flags) = datastore.getSubregistry(tokenId); + return _flags; } } diff --git a/contracts/src/registry/RootRegistry.sol b/contracts/src/registry/RootRegistry.sol index 3414aa9..07ece49 100644 --- a/contracts/src/registry/RootRegistry.sol +++ b/contracts/src/registry/RootRegistry.sol @@ -28,11 +28,12 @@ contract RootRegistry is LockableRegistry, AccessControl { * @param registry The address of the registry to use. * @param flags Flags to set. */ - function mint(string calldata label, address owner, IRegistry registry, uint32 flags) + function mint(string calldata label, address owner, IRegistry registry, uint96 flags) external onlyRole(TLD_ISSUER_ROLE) + returns(uint256 tokenId) { - uint256 tokenId = uint256(keccak256(bytes(label))); + tokenId = uint256(keccak256(bytes(label))); _mint(owner, tokenId, 1, ""); datastore.setSubregistry(tokenId, address(registry), flags); emit NewSubname(label); @@ -53,6 +54,14 @@ contract RootRegistry is LockableRegistry, AccessControl { datastore.setSubregistry(tokenId, address(0), 0); } + function lock(uint256 tokenId, uint96 flags) + external + onlyTokenOwner(tokenId) + returns(uint96) + { + return _lock(tokenId, flags); + } + function supportsInterface(bytes4 interfaceId) public view override(BaseRegistry, AccessControl) returns (bool) { return super.supportsInterface(interfaceId); } diff --git a/contracts/test/ETHRegistry.t.sol b/contracts/test/ETHRegistry.t.sol index 86f95b0..57c5938 100644 --- a/contracts/test/ETHRegistry.t.sol +++ b/contracts/test/ETHRegistry.t.sol @@ -70,4 +70,34 @@ contract TestETHRegistry is Test, ERC1155Holder { registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); registry.register("test2", address(this), registry, 0, uint64(block.timestamp) + 86400); } + + function test_set_subregistry() public { + uint256 tokenId = registry.register("test2", address(this), registry, 0, uint64(block.timestamp) + 86400); + registry.setSubregistry(tokenId, IRegistry(address(this))); + vm.assertEq(address(registry.getSubregistry("test2")), address(this)); + } + + function testFail_cannot_set_locked_subregistry() public { + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED(); + uint256 tokenId = registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); + registry.setSubregistry(tokenId, IRegistry(address(this))); + } + + function test_set_resolver() public { + uint256 tokenId = registry.register("test2", address(this), registry, 0, uint64(block.timestamp) + 86400); + registry.setResolver(tokenId, address(this)); + vm.assertEq(address(registry.getResolver("test2")), address(this)); + } + + function testFail_cannot_set_locked_resolver() public { + uint96 flags = registry.FLAG_RESOLVER_LOCKED(); + uint256 tokenId = registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); + registry.setResolver(tokenId, address(this)); + } + + function testFail_cannot_set_locked_flags() public { + uint96 flags = registry.FLAG_FLAGS_LOCKED(); + uint256 tokenId = registry.register("test2", address(this), registry, flags, uint64(block.timestamp) + 86400); + registry.lock(tokenId, registry.FLAG_RESOLVER_LOCKED()); + } } diff --git a/contracts/test/RootRegistry.t.sol b/contracts/test/RootRegistry.t.sol new file mode 100644 index 0000000..c6edad7 --- /dev/null +++ b/contracts/test/RootRegistry.t.sol @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import "forge-std/Test.sol"; +import "forge-std/console.sol"; + +import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; + +import "src/registry/RootRegistry.sol"; +import "src/registry/RegistryDatastore.sol"; + +contract TestRootRegistry is Test, ERC1155Holder { + event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); + + RegistryDatastore datastore; + RootRegistry registry; + + function setUp() public { + datastore = new RegistryDatastore(); + registry = new RootRegistry(datastore); + registry.grantRole(registry.TLD_ISSUER_ROLE(), address(this)); + } + + function test_register_unlocked() public { + uint256 expectedId = uint256(keccak256("test2")); + 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); + vm.assertEq(tokenId, expectedId); + uint96 flags = registry.flags(tokenId); + vm.assertEq(flags, 0); + } + + function test_register_locked() public { + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint256 expectedId = uint256(keccak256("test2")); + 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); + vm.assertEq(tokenId, expectedId); + uint96 actualFlags = registry.flags(tokenId); + vm.assertEq(flags, actualFlags); + } + + function test_lock_name() public { + uint96 flags = registry.FLAG_SUBREGISTRY_LOCKED() | registry.FLAG_RESOLVER_LOCKED(); + uint256 tokenId = registry.mint("test2", address(this), registry, 0); + uint96 actualFlags = registry.lock(tokenId, flags); + vm.assertEq(flags, actualFlags); + uint96 actualFlags2 = registry.flags(tokenId); + vm.assertEq(flags, actualFlags2); + } + + 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); + uint96 newFlags = registry.lock(tokenId, 0); + vm.assertEq(flags, newFlags); + uint96 newFlags2 = registry.flags(tokenId); + vm.assertEq(flags, newFlags2); + } + + function test_set_subregistry() public { + 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); + registry.setSubregistry(tokenId, IRegistry(address(this))); + } + + function test_set_resolver() public { + 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); + 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); + registry.lock(tokenId, registry.FLAG_RESOLVER_LOCKED()); + } +} From 75606e8124c827400cffaca6d9cf920e7d55f81f Mon Sep 17 00:00:00 2001 From: tate Date: Thu, 29 Aug 2024 13:10:34 +1000 Subject: [PATCH 3/3] fix e2e --- contracts/test/fixtures/deployEnsFixture.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/test/fixtures/deployEnsFixture.ts b/contracts/test/fixtures/deployEnsFixture.ts index 4061b63..3ba86da 100644 --- a/contracts/test/fixtures/deployEnsFixture.ts +++ b/contracts/test/fixtures/deployEnsFixture.ts @@ -19,7 +19,7 @@ export async function deployEnsFixture() { rootRegistry.address, ]); await rootRegistry.write.grantRole([ - keccak256(stringToHex("SUBDOMAIN_ISSUER_ROLE")), + keccak256(stringToHex("TLD_ISSUER_ROLE")), accounts[0].address, ]); await ethRegistry.write.grantRole([ @@ -30,7 +30,7 @@ export async function deployEnsFixture() { "eth", accounts[0].address, ethRegistry.address, - true, + 1n, ]); return { @@ -84,6 +84,6 @@ export const registerName = async ({ }) => { const owner = owner_ ?? (await hre.viem.getWalletClients())[0].account.address; - const flags = (subregistryLocked ? 1 : 0) | (resolverLocked ? 2 : 0); + const flags = (subregistryLocked ? 1n : 0n) | (resolverLocked ? 2n : 0n); return ethRegistry.write.register([label, owner, subregistry, flags, expiry]); };