diff --git a/contracts/interfaces/story-nft/IOrgStoryNFT.sol b/contracts/interfaces/story-nft/IOrgStoryNFT.sol new file mode 100644 index 0000000..673e316 --- /dev/null +++ b/contracts/interfaces/story-nft/IOrgStoryNFT.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IStoryNFT } from "./IStoryNFT.sol"; + +/// @title Organization Story NFT Interface +/// @notice Interface for StoryNFTs with Organization NFT integration. +interface IOrgStoryNFT is IStoryNFT { + /// @notice Initializes the OrgStoryNFT. + /// @param orgTokenId_ The token ID of the organization NFT. + /// @param orgIpId_ The ID of the organization IP. + /// @param initParams The initialization parameters for StoryNFT {see {StoryNftInitParams}}. + function initialize(uint256 orgTokenId_, address orgIpId_, StoryNftInitParams calldata initParams) external; +} diff --git a/contracts/interfaces/story-nft/IStoryNFT.sol b/contracts/interfaces/story-nft/IStoryNFT.sol index 61d0c92..5e3afa1 100644 --- a/contracts/interfaces/story-nft/IStoryNFT.sol +++ b/contracts/interfaces/story-nft/IStoryNFT.sol @@ -36,12 +36,6 @@ interface IStoryNFT is IERC721, IERC7572 { //////////////////////////////////////////////////////////////////////////// // Functions // //////////////////////////////////////////////////////////////////////////// - /// @notice Initializes the StoryNFT. - /// @param orgTokenId_ The token ID of the organization NFT. - /// @param orgIpId_ The ID of the organization IP. - /// @param initParams The initialization parameters for StoryNFT {see {StoryNftInitParams}}. - function initialize(uint256 orgTokenId_, address orgIpId_, StoryNftInitParams calldata initParams) external; - /// @notice Sets the contractURI of the collection (follows OpenSea contract-level metadata standard). function setContractURI(string memory contractURI) external; diff --git a/contracts/interfaces/story-nft/IStoryNFTFactory.sol b/contracts/interfaces/story-nft/IStoryNFTFactory.sol index 8050f56..c596df5 100644 --- a/contracts/interfaces/story-nft/IStoryNFTFactory.sol +++ b/contracts/interfaces/story-nft/IStoryNFTFactory.sol @@ -39,8 +39,8 @@ interface IStoryNFTFactory { error StoryNFTFactory__SignatureAlreadyUsed(bytes signature); /// @notice BaseStoryNFT is not supported by the StoryNFTFactory. - /// @param tokenContract The address of the token contract that does not implement IStoryNFT. - error StoryNFTFactory__UnsupportedIStoryNFT(address tokenContract); + /// @param tokenContract The address of the token contract that does not implement IOrgStoryNFT. + error StoryNFTFactory__UnsupportedIOrgStoryNFT(address tokenContract); /// @notice Zero address provided as a param to StoryNFTFactory functions. error StoryNFTFactory__ZeroAddressParam(); diff --git a/contracts/story-nft/BaseOrgStoryNFT.sol b/contracts/story-nft/BaseOrgStoryNFT.sol new file mode 100644 index 0000000..199ad9c --- /dev/null +++ b/contracts/story-nft/BaseOrgStoryNFT.sol @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol"; + +import { IOrgStoryNFT } from "../interfaces/story-nft/IOrgStoryNFT.sol"; +import { BaseStoryNFT } from "./BaseStoryNFT.sol"; + +/// @title Base Story NFT with OrgNFT integration +/// @notice Base Story NFT which integrates with the OrgNFT and StoryNFTFactory. +abstract contract BaseOrgStoryNFT is IOrgStoryNFT, BaseStoryNFT { + /// @notice Organization NFT address (see {OrgNFT}). + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address public immutable ORG_NFT; + + /// @dev Storage structure for the BaseOrgStoryNFT + /// @param orgTokenId Associated Organization NFT token ID. + /// @param orgIpId Associated Organization IP ID. + /// @custom:storage-location erc7201:story-protocol-periphery.BaseOrgStoryNFT + struct BaseOrgStoryNFTStorage { + uint256 orgTokenId; + address orgIpId; + } + + // keccak256(abi.encode(uint256(keccak256("story-protocol-periphery.BaseOrgStoryNFT")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 private constant BaseOrgStoryNFTStorageLocation = + 0x52eea8b3c549d1bd8b986d98314c387ab153ca0f32b6949d51f32dbd11b07900; + + constructor( + address ipAssetRegistry, + address licensingModule, + address orgNft + ) BaseStoryNFT(ipAssetRegistry, licensingModule) { + if (orgNft == address(0)) revert StoryNFT__ZeroAddressParam(); + ORG_NFT = orgNft; + _disableInitializers(); + } + + /// @dev External initializer function, to be overridden by the inheriting contracts. + /// @param orgTokenId_ The token ID of the organization NFT. + /// @param orgIpId_ The ID of the organization IP. + /// @param initParams The initialization parameters for StoryNFT {see {IStoryNFT-StoryNftInitParams}}. + function initialize( + uint256 orgTokenId_, + address orgIpId_, + StoryNftInitParams calldata initParams + ) external virtual initializer { + __BaseOrgStoryNFT_init(orgTokenId_, orgIpId_, initParams); + } + + /// @dev Initialize the BaseOrgStoryNFT + /// @param orgTokenId_ The token ID of the organization NFT. + /// @param orgIpId_ The ID of the organization IP. + /// @param initParams The initialization parameters for StoryNFT {see {IStoryNFT-StoryNftInitParams}}. + function __BaseOrgStoryNFT_init( + uint256 orgTokenId_, + address orgIpId_, + StoryNftInitParams calldata initParams + ) internal onlyInitializing { + if (orgIpId_ == address(0)) revert StoryNFT__ZeroAddressParam(); + __BaseStoryNFT_init(initParams); + + BaseOrgStoryNFTStorage storage $ = _getBaseOrgStoryNFTStorage(); + $.orgTokenId = orgTokenId_; + $.orgIpId = orgIpId_; + } + + /// @notice Returns the token ID of the associated Organization NFT. + function orgTokenId() public view returns (uint256) { + return _getBaseOrgStoryNFTStorage().orgTokenId; + } + + /// @notice Returns the ID of the associated Organization IP. + function orgIpId() public view returns (address) { + return _getBaseOrgStoryNFTStorage().orgIpId; + } + + /// @notice IERC165 interface support. + function supportsInterface(bytes4 interfaceId) public view virtual override(BaseStoryNFT, IERC165) returns (bool) { + return interfaceId == type(IOrgStoryNFT).interfaceId || super.supportsInterface(interfaceId); + } + + /// @dev Returns the storage struct of BaseOrgStoryNFT. + function _getBaseOrgStoryNFTStorage() private pure returns (BaseOrgStoryNFTStorage storage $) { + assembly { + $.slot := BaseOrgStoryNFTStorageLocation + } + } +} diff --git a/contracts/story-nft/BaseStoryNFT.sol b/contracts/story-nft/BaseStoryNFT.sol index da6c2e9..5234fe5 100644 --- a/contracts/story-nft/BaseStoryNFT.sol +++ b/contracts/story-nft/BaseStoryNFT.sol @@ -2,10 +2,9 @@ pragma solidity 0.8.26; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import { ERC721URIStorage } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +/* solhint-disable-next-line max-line-length */ +import { ERC721URIStorageUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { IIPAssetRegistry } from "@story-protocol/protocol-core/contracts/interfaces/registries/IIPAssetRegistry.sol"; /*solhint-disable-next-line max-line-length*/ import { ILicensingModule } from "@story-protocol/protocol-core/contracts/interfaces/modules/licensing/ILicensingModule.sol"; @@ -17,72 +16,56 @@ import { IStoryNFT } from "../interfaces/story-nft/IStoryNFT.sol"; /// To create a new custom StoryNFT, inherit from this contract and override the required functions. /// Note: the new StoryNFT must be whitelisted in `StoryNFTFactory` by the Story governance in order /// to use the Story NFT Factory features. -abstract contract BaseStoryNFT is IStoryNFT, ERC721URIStorage, Ownable, Initializable { +abstract contract BaseStoryNFT is IStoryNFT, ERC721URIStorageUpgradeable, OwnableUpgradeable { /// @notice Story Proof-of-Creativity IP Asset Registry address. + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IIPAssetRegistry public immutable IP_ASSET_REGISTRY; /// @notice Story Proof-of-Creativity Licensing Module address. + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable ILicensingModule public immutable LICENSING_MODULE; - /// @notice Organization NFT address (see {OrgNFT}). - address public immutable ORG_NFT; - - /// @notice Associated Organization NFT token ID. - uint256 public orgTokenId; - - /// @notice Associated Organization IP ID. - address public orgIpId; - - /// @dev Name of the collection. - string private _name; - - /// @dev Symbol of the collection. - string private _symbol; - - /// @dev Contract URI of the collection (follows OpenSea contract-level metadata standard). - string private _contractURI; - - /// @dev Base URI of the collection (see {ERC721URIStorage-tokenURI} for how it is used). - string private _baseURI_; + /// @dev Storage structure for the BaseStoryNFT + /// @param contractURI The contract URI of the collection. + /// @param baseURI The base URI of the collection. + /// @param totalSupply The total supply of the collection. + /// @custom:storage-location erc7201:story-protocol-periphery.BaseStoryNFT + struct BaseStoryNFTStorage { + string contractURI; + string baseURI; + uint256 totalSupply; + } - /// @dev Current total supply of the collection. - uint256 private _totalSupply; + // keccak256(abi.encode(uint256(keccak256("story-protocol-periphery.BaseStoryNFT")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 private constant BaseStoryNFTStorageLocation = + 0x81ed94d7560ff7bef5060a232718049e514c358c346e3254b876807a753c0e00; - constructor(address ipAssetRegistry, address licensingModule, address orgNft) ERC721("", "") Ownable(msg.sender) { - if (ipAssetRegistry == address(0) || licensingModule == address(0) || orgNft == address(0)) - revert StoryNFT__ZeroAddressParam(); + constructor(address ipAssetRegistry, address licensingModule) { + if (ipAssetRegistry == address(0) || licensingModule == address(0)) revert StoryNFT__ZeroAddressParam(); IP_ASSET_REGISTRY = IIPAssetRegistry(ipAssetRegistry); LICENSING_MODULE = ILicensingModule(licensingModule); - ORG_NFT = orgNft; + + _disableInitializers(); } /// @notice Initializes the StoryNFT - /// @param orgTokenId_ The token ID of the organization NFT. - /// @param orgIpId_ The ID of the organization IP. /// @param initParams The initialization parameters for StoryNFT {see {IStoryNFT-StoryNftInitParams}}. - function initialize( - uint256 orgTokenId_, - address orgIpId_, - StoryNftInitParams calldata initParams - ) public virtual initializer { - if (initParams.owner == address(0) || orgIpId_ == address(0)) revert StoryNFT__ZeroAddressParam(); - - orgTokenId = orgTokenId_; - orgIpId = orgIpId_; - - _name = initParams.name; - _symbol = initParams.symbol; - _contractURI = initParams.contractURI; - _baseURI_ = initParams.baseURI; - - _transferOwnership(initParams.owner); + function __BaseStoryNFT_init(StoryNftInitParams calldata initParams) internal onlyInitializing { + __Ownable_init(initParams.owner); + __ERC721URIStorage_init(); + __ERC721_init(initParams.name, initParams.symbol); + + BaseStoryNFTStorage storage $ = _getBaseStoryNFTStorage(); + $.contractURI = initParams.contractURI; + $.baseURI = initParams.baseURI; + _customize(initParams.customInitData); } /// @notice Sets the contractURI of the collection (follows OpenSea contract-level metadata standard). /// @param contractURI_ The new contractURI of the collection. function setContractURI(string memory contractURI_) external onlyOwner { - _contractURI = contractURI_; + _getBaseStoryNFTStorage().contractURI = contractURI_; emit ContractURIUpdated(); } @@ -104,7 +87,7 @@ abstract contract BaseStoryNFT is IStoryNFT, ERC721URIStorage, Ownable, Initiali address recipient, string memory tokenURI_ ) internal virtual returns (uint256 tokenId, address ipId) { - tokenId = _totalSupply++; + tokenId = _getBaseStoryNFTStorage().totalSupply++; _safeMint(recipient, tokenId); _setTokenURI(tokenId, tokenURI_); ipId = IP_ASSET_REGISTRY.register(block.chainid, address(this), tokenId); @@ -138,28 +121,18 @@ abstract contract BaseStoryNFT is IStoryNFT, ERC721URIStorage, Ownable, Initiali /// @notice IERC165 interface support. function supportsInterface( bytes4 interfaceId - ) public view virtual override(ERC721URIStorage, IERC165) returns (bool) { + ) public view virtual override(ERC721URIStorageUpgradeable, IERC165) returns (bool) { return interfaceId == type(IStoryNFT).interfaceId || super.supportsInterface(interfaceId); } - /// @notice Returns the name of the collection. - function name() public view override returns (string memory) { - return _name; - } - - /// @notice Returns the symbol of the collection. - function symbol() public view override returns (string memory) { - return _symbol; - } - /// @notice Returns the current total supply of the collection. function totalSupply() public view returns (uint256) { - return _totalSupply; + return _getBaseStoryNFTStorage().totalSupply; } /// @notice Returns the contract URI of the collection (follows OpenSea contract-level metadata standard). function contractURI() external view virtual returns (string memory) { - return _contractURI; + return _getBaseStoryNFTStorage().contractURI; } /// @notice Initializes the StoryNFT with custom data, required to be overridden by the inheriting contracts. @@ -169,6 +142,13 @@ abstract contract BaseStoryNFT is IStoryNFT, ERC721URIStorage, Ownable, Initiali /// @notice Returns the base URI of the collection (see {ERC721URIStorage-tokenURI} for how it is used). function _baseURI() internal view virtual override returns (string memory) { - return _baseURI_; + return _getBaseStoryNFTStorage().baseURI; + } + + /// @dev Returns the storage struct of BaseStoryNFT. + function _getBaseStoryNFTStorage() private pure returns (BaseStoryNFTStorage storage $) { + assembly { + $.slot := BaseStoryNFTStorageLocation + } } } diff --git a/contracts/story-nft/StoryBadgeNFT.sol b/contracts/story-nft/StoryBadgeNFT.sol index 9832204..2879229 100644 --- a/contracts/story-nft/StoryBadgeNFT.sol +++ b/contracts/story-nft/StoryBadgeNFT.sol @@ -1,20 +1,21 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.26; -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import { ERC721Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; import { ERC721Holder } from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; -import { ERC721URIStorage } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +/* solhint-disable-next-line max-line-length */ +import { ERC721URIStorageUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721URIStorageUpgradeable.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; -import { BaseStoryNFT } from "./BaseStoryNFT.sol"; +import { BaseOrgStoryNFT } from "./BaseOrgStoryNFT.sol"; import { IStoryBadgeNFT } from "../interfaces/story-nft/IStoryBadgeNFT.sol"; /// @title Story Badge NFT /// @notice A Story Badge is a soulbound NFT that has an unified token URI for all tokens. -contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { +contract StoryBadgeNFT is IStoryBadgeNFT, BaseOrgStoryNFT, ERC721Holder { using MessageHashUtils for bytes32; /// @notice Story Proof-of-Creativity PILicense Template address. @@ -38,7 +39,7 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { address orgNft, address pilTemplate, uint256 defaultLicenseTermsId - ) BaseStoryNFT(ipAssetRegistry, licensingModule, orgNft) { + ) BaseOrgStoryNFT(ipAssetRegistry, licensingModule, orgNft) { if ( ipAssetRegistry == address(0) || licensingModule == address(0) || @@ -82,7 +83,7 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { address[] memory parentIpIds = new address[](1); uint256[] memory licenseTermsIds = new uint256[](1); - parentIpIds[0] = orgIpId; + parentIpIds[0] = orgIpId(); licenseTermsIds[0] = DEFAULT_LICENSE_TERMS_ID; // Make the badge a derivative of the organization IP @@ -111,14 +112,16 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { /// @notice Returns the token URI for the given token ID. /// @param tokenId The token ID. /// @return The unified token URI for all badges. - function tokenURI(uint256 tokenId) public view override(ERC721URIStorage, IERC721Metadata) returns (string memory) { + function tokenURI( + uint256 tokenId + ) public view override(ERC721URIStorageUpgradeable, IERC721Metadata) returns (string memory) { return _tokenURI; } /// @notice Initializes the StoryBadgeNFT with custom data (see {IStoryBadgeNFT-CustomInitParams}). /// @dev This function is called by BaseStoryNFT's `initialize` function. /// @param customInitData The custom data to initialize the StoryBadgeNFT. - function _customize(bytes memory customInitData) internal override { + function _customize(bytes memory customInitData) internal override onlyInitializing { CustomInitParams memory customParams = abi.decode(customInitData, (CustomInitParams)); if (customParams.signer == address(0)) revert StoryBadgeNFT__ZeroAddressParam(); @@ -136,15 +139,15 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { // Locked Functions // //////////////////////////////////////////////////////////////////////////// - function approve(address to, uint256 tokenId) public pure override(ERC721, IERC721) { + function approve(address to, uint256 tokenId) public pure override(ERC721Upgradeable, IERC721) { revert StoryBadgeNFT__TransferLocked(); } - function setApprovalForAll(address operator, bool approved) public pure override(ERC721, IERC721) { + function setApprovalForAll(address operator, bool approved) public pure override(ERC721Upgradeable, IERC721) { revert StoryBadgeNFT__TransferLocked(); } - function transferFrom(address from, address to, uint256 tokenId) public pure override(ERC721, IERC721) { + function transferFrom(address from, address to, uint256 tokenId) public pure override(ERC721Upgradeable, IERC721) { revert StoryBadgeNFT__TransferLocked(); } @@ -153,7 +156,7 @@ contract StoryBadgeNFT is IStoryBadgeNFT, BaseStoryNFT, ERC721Holder { address to, uint256 tokenId, bytes memory data - ) public pure override(ERC721, IERC721) { + ) public pure override(ERC721Upgradeable, IERC721) { revert StoryBadgeNFT__TransferLocked(); } } diff --git a/contracts/story-nft/StoryNFTFactory.sol b/contracts/story-nft/StoryNFTFactory.sol index 0bb13db..eecb88b 100644 --- a/contracts/story-nft/StoryNFTFactory.sol +++ b/contracts/story-nft/StoryNFTFactory.sol @@ -9,8 +9,9 @@ import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/Mes import { SignatureChecker } from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IStoryNFT } from "../interfaces/story-nft/IStoryNFT.sol"; +import { IOrgStoryNFT } from "../interfaces/story-nft/IOrgStoryNFT.sol"; import { IOrgNFT } from "../interfaces/story-nft/IOrgNFT.sol"; +import { IStoryNFT } from "../interfaces/story-nft/IStoryNFT.sol"; import { IStoryNFTFactory } from "../interfaces/story-nft/IStoryNFTFactory.sol"; /// @title StoryNFTFactory @@ -148,7 +149,7 @@ contract StoryNFTFactory is IStoryNFTFactory, AccessManagedUpgradeable, UUPSUpgr // Clones the story NFT template and initializes it storyNft = Clones.clone(storyNftTemplate); - IStoryNFT(storyNft).initialize(orgTokenId, orgIpId, storyNftInitParams); + IOrgStoryNFT(storyNft).initialize(orgTokenId, orgIpId, storyNftInitParams); // Stores the deployed story NFT address $.deployedStoryNftsByOrgName[orgName] = storyNft; @@ -200,7 +201,7 @@ contract StoryNFTFactory is IStoryNFTFactory, AccessManagedUpgradeable, UUPSUpgr // Clones the story NFT template and initializes it storyNft = Clones.clone(storyNftTemplate); - IStoryNFT(storyNft).initialize(orgTokenId, orgIpId, storyNftInitParams); + IOrgStoryNFT(storyNft).initialize(orgTokenId, orgIpId, storyNftInitParams); // Stores the deployed story NFT address $.deployedStoryNftsByOrgName[orgName] = storyNft; @@ -215,8 +216,8 @@ contract StoryNFTFactory is IStoryNFTFactory, AccessManagedUpgradeable, UUPSUpgr /// @param defaultStoryNftTemplate The new default StoryNFT template. function setDefaultStoryNftTemplate(address defaultStoryNftTemplate) external restricted { if (defaultStoryNftTemplate == address(0)) revert StoryNFTFactory__ZeroAddressParam(); - if (!defaultStoryNftTemplate.supportsInterface(type(IStoryNFT).interfaceId)) - revert StoryNFTFactory__UnsupportedIStoryNFT(defaultStoryNftTemplate); + if (!defaultStoryNftTemplate.supportsInterface(type(IOrgStoryNFT).interfaceId)) + revert StoryNFTFactory__UnsupportedIOrgStoryNFT(defaultStoryNftTemplate); _getStoryNFTFactoryStorage().whitelistedNftTemplates[defaultStoryNftTemplate] = true; _getStoryNFTFactoryStorage().defaultStoryNftTemplate = defaultStoryNftTemplate; @@ -238,9 +239,9 @@ contract StoryNFTFactory is IStoryNFTFactory, AccessManagedUpgradeable, UUPSUpgr function whitelistNftTemplate(address storyNftTemplate) external restricted { if (storyNftTemplate == address(0)) revert StoryNFTFactory__ZeroAddressParam(); - // The given story NFT template must implement IStoryNFT - if (!storyNftTemplate.supportsInterface(type(IStoryNFT).interfaceId)) - revert StoryNFTFactory__UnsupportedIStoryNFT(storyNftTemplate); + // The given story NFT template must implement IOrgStoryNFT + if (!storyNftTemplate.supportsInterface(type(IOrgStoryNFT).interfaceId)) + revert StoryNFTFactory__UnsupportedIOrgStoryNFT(storyNftTemplate); _getStoryNFTFactoryStorage().whitelistedNftTemplates[storyNftTemplate] = true; emit StoryNFTFactoryNftTemplateWhitelisted(storyNftTemplate); diff --git a/test/story-nft/StoryBadgeNFT.t.sol b/test/story-nft/StoryBadgeNFT.t.sol index 518b606..423ebfd 100644 --- a/test/story-nft/StoryBadgeNFT.t.sol +++ b/test/story-nft/StoryBadgeNFT.t.sol @@ -10,6 +10,7 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; // contracts import { BaseStoryNFT } from "../../contracts/story-nft/BaseStoryNFT.sol"; import { IStoryBadgeNFT } from "../../contracts/interfaces/story-nft/IStoryBadgeNFT.sol"; +import { IOrgStoryNFT } from "../../contracts/interfaces/story-nft/IOrgStoryNFT.sol"; import { IStoryNFT } from "../../contracts/interfaces/story-nft/IStoryNFT.sol"; import { StoryBadgeNFT } from "../../contracts/story-nft/StoryBadgeNFT.sol"; @@ -51,7 +52,7 @@ contract StoryBadgeNFTTest is BaseTest { StoryBadgeNFT testStoryBadgeNft = StoryBadgeNFT( TestProxyHelper.deployUUPSProxy( testStoryBadgeNftImpl, - abi.encodeCall(IStoryNFT.initialize, (0, address(1), storyBadgeNftInitParams)) + abi.encodeCall(IOrgStoryNFT.initialize, (0, address(1), storyBadgeNftInitParams)) ) ); @@ -111,13 +112,13 @@ contract StoryBadgeNFTTest is BaseTest { testStoryBadgeNft = StoryBadgeNFT( TestProxyHelper.deployUUPSProxy( testStoryBadgeNftImpl, - abi.encodeCall(IStoryNFT.initialize, (0, address(1), storyBadgeNftInitParams)) + abi.encodeCall(IOrgStoryNFT.initialize, (0, address(1), storyBadgeNftInitParams)) ) ); } function test_StoryBadgeNFT_interfaceSupport() public { - assertTrue(BaseStoryNFT(rootStoryNft).supportsInterface(type(IStoryNFT).interfaceId)); + assertTrue(BaseStoryNFT(rootStoryNft).supportsInterface(type(IOrgStoryNFT).interfaceId)); assertTrue(BaseStoryNFT(rootStoryNft).supportsInterface(type(IERC721).interfaceId)); assertTrue(BaseStoryNFT(rootStoryNft).supportsInterface(type(IERC721Metadata).interfaceId)); } diff --git a/test/story-nft/StoryNFTFactory.t.sol b/test/story-nft/StoryNFTFactory.t.sol index fb0369a..61afee5 100644 --- a/test/story-nft/StoryNFTFactory.t.sol +++ b/test/story-nft/StoryNFTFactory.t.sol @@ -256,7 +256,7 @@ contract StoryNFTFactoryTest is BaseTest { storyNftFactory.setDefaultStoryNftTemplate(address(0)); vm.expectRevert( - abi.encodeWithSelector(IStoryNFTFactory.StoryNFTFactory__UnsupportedIStoryNFT.selector, address(orgNft)) + abi.encodeWithSelector(IStoryNFTFactory.StoryNFTFactory__UnsupportedIOrgStoryNFT.selector, address(orgNft)) ); storyNftFactory.setDefaultStoryNftTemplate(address(orgNft)); vm.stopPrank(); @@ -272,7 +272,7 @@ contract StoryNFTFactoryTest is BaseTest { storyNftFactory.whitelistNftTemplate(address(0)); vm.expectRevert( - abi.encodeWithSelector(IStoryNFTFactory.StoryNFTFactory__UnsupportedIStoryNFT.selector, address(orgNft)) + abi.encodeWithSelector(IStoryNFTFactory.StoryNFTFactory__UnsupportedIOrgStoryNFT.selector, address(orgNft)) ); storyNftFactory.whitelistNftTemplate(address(orgNft)); vm.stopPrank();