@@ -4,162 +4,105 @@ pragma experimental ABIEncoderV2;
44import "./Governed.sol " ;
55
66
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+ */
713contract 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 {
2419 address owner;
2520 bytes32 subgraphID;
21+ RecordType nameSystem;
2622 }
2723
28- /* STATE VARIABLES */
29- // Storage of a hashed top level domain to owners.
30- mapping (bytes32 => Domain) public domains;
24+ // -- State --
3125
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;
3527
36- /* Graph Protocol Functions */
28+ // -- Events --
3729
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 );
4235
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.
4638 */
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 );
5440
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.
6543 */
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+ _;
9349 }
9450
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
10154 */
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));
10670 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 "
10973 );
110- domains[_domainHash].subgraphID = _subgraphID;
111- emit SubgraphIDUpdated (_domainHash, _subgraphID);
112- }
11374
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);
12377 }
12478
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
13182 */
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);
13986 }
14087
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
14792 */
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);
15098 }
15199
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
158104 */
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 );
164107 }
165108}
0 commit comments