@@ -4,162 +4,105 @@ pragma experimental ABIEncoderV2;
4
4
import "./Governed.sol " ;
5
5
6
6
7
+ /**
8
+ * @title GNS
9
+ * @dev The Graph Name System contract provides a decentralized namings system for subgraphs
10
+ * used in the scope of the Graph Network. It translate subgraph names into subgraphID regarded as
11
+ * versions.
12
+ */
7
13
contract GNS is Governed {
8
- /* Events */
9
- event DomainAdded (bytes32 indexed topLevelDomainHash , address indexed owner , string domainName );
10
- event DomainTransferred (bytes32 indexed domainHash , address indexed newOwner );
11
- event SubgraphCreated (
12
- bytes32 indexed topLevelDomainHash ,
13
- bytes32 indexed registeredHash ,
14
- string subdomainName ,
15
- address indexed owner
16
- );
17
- event SubgraphIDUpdated (bytes32 indexed domainHash , bytes32 indexed subgraphID );
18
- event DomainDeleted (bytes32 indexed domainHash );
19
- event AccountMetadataChanged (address indexed account , bytes32 indexed ipfsHash );
20
- event SubgraphMetadataChanged (bytes32 indexed domainHash , bytes32 indexed ipfsHash );
21
-
22
- /* TYPES */
23
- struct Domain {
14
+ // -- Types --
15
+
16
+ enum RecordType { GNS }
17
+
18
+ struct Record {
24
19
address owner;
25
20
bytes32 subgraphID;
21
+ RecordType nameSystem;
26
22
}
27
23
28
- /* STATE VARIABLES */
29
- // Storage of a hashed top level domain to owners.
30
- mapping (bytes32 => Domain) public domains;
24
+ // -- State --
31
25
32
- /* Contract Constructor */
33
- /* @param _governor <address> - Address of the multisig contract as Governor */
34
- constructor (address _governor ) public Governed (_governor) {}
26
+ mapping (bytes32 => Record) public records;
35
27
36
- /* Graph Protocol Functions */
28
+ // -- Events --
37
29
38
- modifier onlyDomainOwner (bytes32 _domainHash ) {
39
- require (msg .sender == domains[_domainHash].owner, "Only domain owner can call. " );
40
- _;
41
- }
30
+ /**
31
+ * @dev Emitted when `owner` publish a `subgraphID` version under subgraph `name`.
32
+ * The event also attach `metadataHash` with extra information.
33
+ */
34
+ event SubgraphPublished (string name , address owner , bytes32 subgraphID , bytes32 metadataHash );
42
35
43
- /*
44
- * @notice Register a domain to an owner.
45
- * @param _domainName <string> - Domain name, which is treated as a username.
36
+ /**
37
+ * @dev Emitted when subgraph `nameHash` is unpublished by its owner.
46
38
*/
47
- function registerDomain (string calldata _domainName ) external {
48
- bytes32 hashedName = keccak256 (abi.encodePacked (_domainName));
49
- // Require that this domain is not yet owned by anyone.
50
- require (domains[hashedName].owner == address (0 ), "Domain is already owned. " );
51
- domains[hashedName].owner = msg .sender ;
52
- emit DomainAdded (hashedName, msg .sender , _domainName);
53
- }
39
+ event SubgraphUnpublished (bytes32 nameHash );
54
40
55
- /*
56
- * @notice Create a subgraph by registering a subdomain, or registering the top level
57
- * domain as a subgraph.
58
- * @notice To register to the top level domain, pass _subdomainName as a blank string.
59
- * @dev Only the domain owner may do this.
60
- *
61
- * @param _topLevelDomainHash <bytes32> - Hash of the top level domain name.
62
- * @param _subdomainName <string> - Name of the Subdomain. If you were
63
- * registering 'david.thegraph', _subdomainName would be just 'david'.
64
- * @param _ipfsHash <bytes32> - Hash of the subgraph metadata, such as description.
41
+ /**
42
+ * @dev Emitted when subgraph `nameHash` is transferred to new owner.
65
43
*/
66
- function createSubgraph (
67
- bytes32 _topLevelDomainHash ,
68
- string calldata _subdomainName ,
69
- bytes32 _ipfsHash
70
- ) external onlyDomainOwner (_topLevelDomainHash) {
71
- bytes32 domainHash;
72
- bytes32 subdomainHash = keccak256 (abi.encodePacked (_subdomainName));
73
-
74
- // Subdomain is blank, therefore we are setting the subgraphID of the top level domain
75
- if (subdomainHash == keccak256 ("" )) {
76
- // The domain hash ends up being the top level domain hash.
77
- domainHash = _topLevelDomainHash;
78
- } else {
79
- // The domain hash becomes the subdomain concatenated with the top level domain hash.
80
- domainHash = keccak256 (abi.encodePacked (subdomainHash, _topLevelDomainHash));
81
- require (
82
- domains[domainHash].owner == address (0 ),
83
- "Someone already owns this subdomain. "
84
- );
85
- domains[domainHash].owner = msg .sender ;
86
- }
87
-
88
- // Note - subdomain name and IPFS hash are only emitted through the events.
89
- // Note - if the subdomain is blank, the domain hash ends up being the top level
90
- // domain hash, not the hash of a blank string.
91
- emit SubgraphCreated (_topLevelDomainHash, domainHash, _subdomainName, msg .sender );
92
- emit SubgraphMetadataChanged (domainHash, _ipfsHash);
44
+ event SubgraphTransferred (bytes32 nameHash , address from , address to );
45
+
46
+ modifier onlyRecordOwner (bytes32 _nameHash ) {
47
+ require (msg .sender == records[_nameHash].owner, "GNS: Only record owner can call " );
48
+ _;
93
49
}
94
50
95
- /*
96
- * @notice Update an existing subdomain with a subgraph ID.
97
- * @dev Only the domain owner may do this.
98
- *
99
- * @param _domainHash <bytes32> - Hash of the domain name.
100
- * @param _subgraphID <bytes32> - IPLD subgraph ID of the domain.
51
+ /**
52
+ * @dev Contract Constructor
53
+ * @param _governor Owner address of this contract
101
54
*/
102
- function updateDomainSubgraphID (bytes32 _domainHash , bytes32 _subgraphID )
103
- external
104
- onlyDomainOwner (_domainHash)
105
- {
55
+ constructor (address _governor ) public Governed (_governor) {}
56
+
57
+ /**
58
+ * @dev Publish a version using `subgraphID` under a subgraph name.
59
+ * @param _name Name of the subgraph
60
+ * @param _subgraphID Subgraph ID to link to the subgraph name
61
+ * @param _metadataHash IPFS hash linked to the metadata
62
+ */
63
+ function publish (
64
+ string calldata _name ,
65
+ bytes32 _subgraphID ,
66
+ bytes32 _metadataHash
67
+ ) external {
68
+ address owner = msg .sender ;
69
+ bytes32 nameHash = keccak256 (bytes (_name));
106
70
require (
107
- _subgraphID != bytes32 ( 0 ) ,
108
- "If you want to reset the subgraphID, call deleteSubdomain. "
71
+ ! isReserved (nameHash) || records[nameHash].owner == owner ,
72
+ "GNS: Record reserved, only record owner can publish "
109
73
);
110
- domains[_domainHash].subgraphID = _subgraphID;
111
- emit SubgraphIDUpdated (_domainHash, _subgraphID);
112
- }
113
74
114
- /*
115
- * @notice Remove an existing domain owner and subgraphID
116
- * @dev Only the domain owner may do this.
117
- *
118
- * @param _domainHash <bytes32> - Hash of the domain name.
119
- */
120
- function deleteSubdomain (bytes32 _domainHash ) external onlyDomainOwner (_domainHash) {
121
- delete domains[_domainHash];
122
- emit DomainDeleted (_domainHash);
75
+ records[nameHash] = Record (owner, _subgraphID, RecordType.GNS);
76
+ emit SubgraphPublished (_name, owner, _subgraphID, _metadataHash);
123
77
}
124
78
125
- /*
126
- * @notice Transfer ownership of domain by existing domain owner.
127
- * @dev Only the domain owner may do this.
128
- *
129
- * @param _domainHash <bytes32> - Hash of the domain name.
130
- * @param _newOwner <address> - New owner of the domain.
79
+ /**
80
+ * @dev Unpublish a subgraph name. Can only be done by the owner.
81
+ * @param _nameHash Keccak256 hash of the subgraph name
131
82
*/
132
- function transferDomainOwnership (bytes32 _domainHash , address _newOwner )
133
- external
134
- onlyDomainOwner (_domainHash)
135
- {
136
- require (_newOwner != address (0 ), "If you want to reset the owner, call deleteSubdomain. " );
137
- domains[_domainHash].owner = _newOwner;
138
- emit DomainTransferred (_domainHash, _newOwner);
83
+ function unpublish (bytes32 _nameHash ) external onlyRecordOwner (_nameHash) {
84
+ delete records[_nameHash];
85
+ emit SubgraphUnpublished (_nameHash);
139
86
}
140
87
141
- /*
142
- * @notice Change or initalize the Account Metadata, which is stored in a schema on IPFS.
143
- * @dev Only the msg.sender can do this.
144
- *
145
- * @param _ipfsHash <bytes32> - Hash of the IPFS file that stores the account metadata.
146
- * @param _account <address> - msg.sender.
88
+ /**
89
+ * @dev Tranfer the subgraph name to a new owner.
90
+ * @param _nameHash Keccak256 hash of the subgraph name
91
+ * @param _to Address of the new owner
147
92
*/
148
- function changeAccountMetadata (bytes32 _ipfsHash ) external {
149
- emit AccountMetadataChanged (msg .sender , _ipfsHash);
93
+ function transfer (bytes32 _nameHash , address _to ) external onlyRecordOwner (_nameHash) {
94
+ require (_to != address (0 ), "GNS: Cannot transfer to empty address " );
95
+ require (records[_nameHash].owner != _to, "GNS: Cannot transfer to itself " );
96
+ records[_nameHash].owner = _to;
97
+ emit SubgraphTransferred (_nameHash, msg .sender , _to);
150
98
}
151
99
152
- /*
153
- * @notice Change or initalize the Account Metadata, which is stored in a schema on IPFS.
154
- * @dev Only the msg.sender can do this.
155
- *
156
- * @param _ipfsHash <bytes32> - Hash of the IPFS file that stores the subgraph metadata.
157
- * @param _domainHash <bytes32> - Hash of the domain name.
100
+ /**
101
+ * @dev Return whether a subgraph name is registed or not.
102
+ * @param _nameHash Keccak256 hash of the subgraph name
103
+ * @return Return true if subgraph name exists
158
104
*/
159
- function changeSubgraphMetadata (bytes32 _domainHash , bytes32 _ipfsHash )
160
- public
161
- onlyDomainOwner (_domainHash)
162
- {
163
- emit SubgraphMetadataChanged (_domainHash, _ipfsHash);
105
+ function isReserved (bytes32 _nameHash ) public view returns (bool ) {
106
+ return records[_nameHash].owner != address (0 );
164
107
}
165
108
}
0 commit comments