forked from ensdomains/namechain
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathETHRegistry.sol
117 lines (100 loc) · 4.33 KB
/
ETHRegistry.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// 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";
import {LockableRegistry} from "./LockableRegistry.sol";
contract ETHRegistry is LockableRegistry, AccessControl {
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
error NameAlreadyRegistered(string label);
error NameExpired(uint256 tokenId);
error CannotReduceExpiration(uint64 oldExpiration, uint64 newExpiration);
constructor(IRegistryDatastore _datastore) LockableRegistry(_datastore) {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function uri(uint256 /*tokenId*/ ) public pure override returns (string memory) {
return "";
}
function ownerOf(uint256 tokenId)
public
view
virtual
override(ERC1155Singleton, IERC1155Singleton)
returns (address)
{
(, uint96 flags) = datastore.getSubregistry(tokenId);
uint64 expires = uint64(flags);
if (expires < block.timestamp) {
return address(0);
}
return super.ownerOf(tokenId);
}
function register(string calldata label, address owner, IRegistry registry, uint96 flags, uint64 expires)
public
onlyRole(REGISTRAR_ROLE)
returns (uint256 tokenId)
{
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);
if (oldExpiry >= block.timestamp) {
revert NameAlreadyRegistered(label);
}
_mint(owner, tokenId, 1, "");
datastore.setSubregistry(tokenId, address(registry), flags);
emit NewSubname(label);
return tokenId;
}
function renew(uint256 tokenId, uint64 expires) public onlyRole(REGISTRAR_ROLE) {
(address subregistry, uint96 flags) = datastore.getSubregistry(tokenId);
uint64 oldExpiration = uint64(flags >> 32);
if (oldExpiration < block.timestamp) {
revert NameExpired(tokenId);
}
if (expires < oldExpiration) {
revert CannotReduceExpiration(oldExpiration, expires);
}
datastore.setSubregistry(tokenId, subregistry, (flags & FLAGS_MASK) | (uint96(expires) << 32));
}
function nameData(uint256 tokenId) external view returns (uint64 expiry, uint32 flags) {
(, uint96 _flags) = datastore.getSubregistry(tokenId);
return (uint64(_flags >> 32), uint32(_flags));
}
function lock(uint256 tokenId, uint96 flags)
external
onlyTokenOwner(tokenId)
returns (uint256 newTokenId)
{
uint96 newFlags = _lock(tokenId, flags);
newTokenId = (tokenId & ~uint256(FLAGS_MASK)) | (newFlags & FLAGS_MASK);
if (tokenId != newTokenId) {
address owner = ownerOf(tokenId);
_burn(owner, tokenId, 1);
_mint(owner, newTokenId, 1, "");
}
}
function supportsInterface(bytes4 interfaceId) public view override(BaseRegistry, AccessControl) returns (bool) {
return interfaceId == type(IRegistry).interfaceId || super.supportsInterface(interfaceId);
}
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) {
return IRegistry(address(0));
}
return IRegistry(subregistry);
}
function getResolver(string calldata label) external view virtual override returns (address) {
(address subregistry, uint96 flags) = datastore.getSubregistry(uint256(keccak256(bytes(label))));
uint64 expires = uint64(flags);
if (expires <= block.timestamp) {
return address(0);
}
(address resolver, ) = datastore.getResolver(uint256(keccak256(bytes(label))));
return resolver;
}
}