@@ -4,9 +4,9 @@ pragma solidity ^0.7.6;
44pragma abicoder v2;
55
66import "@openzeppelin/contracts/math/SafeMath.sol " ;
7+ import "@openzeppelin/contracts/utils/Address.sol " ;
78
89import "../base/Multicall.sol " ;
9- import "../base/SubgraphNFT.sol " ;
1010import "../bancor/BancorFormula.sol " ;
1111import "../upgrades/GraphUpgradeable.sol " ;
1212import "../utils/TokenUtils.sol " ;
@@ -38,6 +38,8 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
3838
3939 // -- Events --
4040
41+ event SubgraphNFTUpdated (address subgraphNFT );
42+
4143 /**
4244 * @dev Emitted when graph account sets its default name
4345 */
@@ -143,16 +145,16 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
143145 function initialize (
144146 address _controller ,
145147 address _bondingCurve ,
146- address _tokenDescriptor
148+ address _subgraphNFT
147149 ) external onlyImpl {
148150 Managed._initialize (_controller);
149151
150152 // Dependencies
151153 bondingCurve = _bondingCurve;
152- __SubgraphNFT_init (_tokenDescriptor);
153154
154155 // Settings
155156 _setOwnerTaxPercentage (500000 );
157+ _setSubgraphNFT (_subgraphNFT);
156158 }
157159
158160 /**
@@ -162,6 +164,8 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
162164 graphToken ().approve (address (curation ()), MAX_UINT256);
163165 }
164166
167+ // -- Config --
168+
165169 /**
166170 * @dev Set the owner fee percentage. This is used to prevent a subgraph owner to drain all
167171 * the name curators tokens while upgrading or deprecating and is configurable in parts per million.
@@ -171,14 +175,6 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
171175 _setOwnerTaxPercentage (_ownerTaxPercentage);
172176 }
173177
174- /**
175- * @dev Set the token descriptor contract.
176- * @param _tokenDescriptor Address of the contract that creates the NFT token URI
177- */
178- function setTokenDescriptor (address _tokenDescriptor ) external override onlyGovernor {
179- _setTokenDescriptor (_tokenDescriptor);
180- }
181-
182178 /**
183179 * @dev Internal: Set the owner tax percentage. This is used to prevent a subgraph owner to drain all
184180 * the name curators tokens while upgrading or deprecating and is configurable in parts per million.
@@ -190,6 +186,32 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
190186 emit ParameterUpdated ("ownerTaxPercentage " );
191187 }
192188
189+ /**
190+ * @dev Set the NFT registry contract
191+ * NOTE: Calling this function will break the ownership model unless
192+ * it is replaced with a fully migrated version of the NFT contract state
193+ * Use with care.
194+ * @param _subgraphNFT Address of the ERC721 contract
195+ */
196+ function setSubgraphNFT (address _subgraphNFT ) public onlyGovernor {
197+ _setSubgraphNFT (_subgraphNFT);
198+ }
199+
200+ /**
201+ * @dev Internal: Set the NFT registry contract
202+ * @param _subgraphNFT Address of the ERC721 contract
203+ */
204+ function _setSubgraphNFT (address _subgraphNFT ) private {
205+ require (
206+ _subgraphNFT != address (0 ) && Address.isContract (_subgraphNFT),
207+ "NFT must be valid "
208+ );
209+ subgraphNFT = ISubgraphNFT (_subgraphNFT);
210+ emit SubgraphNFTUpdated (_subgraphNFT);
211+ }
212+
213+ // -- Actions --
214+
193215 /**
194216 * @dev Allows a graph account to set a default name
195217 * @param _graphAccount Account that is setting its name
@@ -217,7 +239,7 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
217239 override
218240 onlySubgraphAuth (_subgraphID)
219241 {
220- emit SubgraphMetadataUpdated (_subgraphID, _subgraphMetadata);
242+ _setSubgraphMetadata (_subgraphID, _subgraphMetadata);
221243 }
222244
223245 /**
@@ -241,12 +263,14 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
241263 subgraphData.subgraphDeploymentID = _subgraphDeploymentID;
242264 subgraphData.reserveRatio = defaultReserveRatio;
243265
244- // Mint the NFT. Use the subgraphID as tokenId.
245- // This function will check the if tokenId already exists.
246- _mint (subgraphOwner, subgraphID);
247-
266+ // Mint the NFT. Use the subgraphID as tokenID.
267+ // This function will check the if tokenID already exists.
268+ _mintNFT (subgraphOwner, subgraphID);
248269 emit SubgraphPublished (subgraphID, _subgraphDeploymentID, defaultReserveRatio);
249- emit SubgraphMetadataUpdated (subgraphID, _subgraphMetadata);
270+
271+ // Set the token metadata
272+ _setSubgraphMetadata (subgraphID, _subgraphMetadata);
273+
250274 emit SubgraphVersionUpdated (subgraphID, _subgraphDeploymentID, _versionMetadata);
251275 }
252276
@@ -356,7 +380,7 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
356380 // subgraphData.subgraphDeploymentID = 0;
357381
358382 // Burn the NFT
359- _burn (_subgraphID);
383+ _burnNFT (_subgraphID);
360384
361385 emit SubgraphDeprecated (_subgraphID, subgraphData.withdrawableGRT);
362386 }
@@ -637,21 +661,17 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
637661 return 0 ;
638662 }
639663
640- /**
641- * @dev Return the URI describing a particular token ID for a Subgraph.
642- * @param _subgraphID Subgraph ID
643- * @return The URI of the ERC721-compliant metadata
644- */
645- function tokenURI (uint256 _subgraphID ) public view override returns (string memory ) {
646- return tokenDescriptor.tokenURI (this , _subgraphID);
647- }
648-
649664 /**
650665 * @dev Create subgraphID for legacy subgraph and mint ownership NFT.
651666 * @param _graphAccount Account that created the subgraph
652667 * @param _subgraphNumber The sequence number of the created subgraph
668+ * @param _subgraphMetadata IPFS hash for the subgraph metadata
653669 */
654- function migrateLegacySubgraph (address _graphAccount , uint256 _subgraphNumber ) external {
670+ function migrateLegacySubgraph (
671+ address _graphAccount ,
672+ uint256 _subgraphNumber ,
673+ bytes32 _subgraphMetadata
674+ ) external {
655675 // Must be an existing legacy subgraph
656676 bool legacySubgraphExists = legacySubgraphData[_graphAccount][_subgraphNumber]
657677 .subgraphDeploymentID != 0 ;
@@ -675,9 +695,11 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
675695
676696 // Mint the NFT and send to owner
677697 // The subgraph owner is the graph account that created it
678- _mint (_graphAccount, subgraphID);
679-
698+ _mintNFT (_graphAccount, subgraphID);
680699 emit LegacySubgraphClaimed (_graphAccount, _subgraphNumber);
700+
701+ // Set the token metadata
702+ _setSubgraphMetadata (subgraphID, _subgraphMetadata);
681703 }
682704
683705 /**
@@ -757,4 +779,45 @@ contract GNS is GNSV2Storage, GraphUpgradeable, IGNS, Multicall {
757779 require (_isPublished (subgraphData) == true , "GNS: Must be active " );
758780 return subgraphData;
759781 }
782+
783+ // -- NFT --
784+
785+ /**
786+ * @dev Return the owner of a subgraph.
787+ * @param _tokenID Subgraph ID
788+ * @return Owner address
789+ */
790+ function ownerOf (uint256 _tokenID ) public view override returns (address ) {
791+ return subgraphNFT.ownerOf (_tokenID);
792+ }
793+
794+ /**
795+ * @dev Mint the NFT for the subgraph.
796+ * @param _owner Owner address
797+ * @param _tokenID Subgraph ID
798+ */
799+ function _mintNFT (address _owner , uint256 _tokenID ) internal {
800+ subgraphNFT.mint (_owner, _tokenID);
801+ }
802+
803+ /**
804+ * @dev Burn the NFT for the subgraph.
805+ * @param _tokenID Subgraph ID
806+ */
807+ function _burnNFT (uint256 _tokenID ) internal {
808+ subgraphNFT.burn (_tokenID);
809+ }
810+
811+ /**
812+ * @dev Set the subgraph metadata.
813+ * @param _tokenID Subgraph ID
814+ * @param _subgraphMetadata IPFS hash of the subgraph metadata
815+ */
816+ function _setSubgraphMetadata (uint256 _tokenID , bytes32 _subgraphMetadata ) internal {
817+ subgraphNFT.setSubgraphMetadata (_tokenID, _subgraphMetadata);
818+
819+ // Even if the following event is emitted in the NFT we emit it here to facilitate
820+ // subgraph indexing
821+ emit SubgraphMetadataUpdated (_tokenID, _subgraphMetadata);
822+ }
760823}
0 commit comments