diff --git a/contracts/GroupingWorkflow.sol b/contracts/GroupingWorkflows.sol similarity index 91% rename from contracts/GroupingWorkflow.sol rename to contracts/GroupingWorkflows.sol index 780947c..e8a556e 100644 --- a/contracts/GroupingWorkflow.sol +++ b/contracts/GroupingWorkflows.sol @@ -20,14 +20,14 @@ import { ISPGNFT } from "./interfaces/ISPGNFT.sol"; import { MetadataHelper } from "./lib/MetadataHelper.sol"; import { LicensingHelper } from "./lib/LicensingHelper.sol"; import { PermissionHelper } from "./lib/PermissionHelper.sol"; -import { IGroupingWorkflow } from "./interfaces/IGroupingWorkflow.sol"; +import { IGroupingWorkflows } from "./interfaces/IGroupingWorkflows.sol"; import { IStoryProtocolGateway as ISPG } from "./interfaces/IStoryProtocolGateway.sol"; -/// @title Grouping Workflow +/// @title Grouping Workflows /// @notice This contract provides key workflows for engaging with Group IPA features in /// Story’s Proof of Creativity protocol. -contract GroupingWorkflow is - IGroupingWorkflow, +contract GroupingWorkflows is + IGroupingWorkflows, BaseWorkflow, MulticallUpgradeable, AccessManagedUpgradeable, @@ -37,16 +37,15 @@ contract GroupingWorkflow is /// @dev Storage structure for the Grouping Workflow. /// @param nftContractBeacon The address of the NFT contract beacon. - /// @custom:storage-location erc7201:story-protocol-periphery.GroupingWorkflow - struct GroupingWorkflowStorage { + /// @custom:storage-location erc7201:story-protocol-periphery.GroupingWorkflows + struct GroupingWorkflowsStorage { address nftContractBeacon; } - /* solhint-disable */ - // keccak256(abi.encode(uint256(keccak256("story-protocol-periphery.GroupingWorkflow")) - 1)) & ~bytes32(uint256(0xff)); - bytes32 private constant GroupingWorkflowStorageLocation = - 0x4857a9bcc504d5c12cd2c114418794d56adfd4110e9bf90f57ba93c59e7f6200; - /* solhint-enable */ + // solhint-disable-next-line max-line-length + // keccak256(abi.encode(uint256(keccak256("story-protocol-periphery.GroupingWorkflows")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 private constant GroupingWorkflowsStorageLocation = + 0xa8ddbb5f662015e2b3d6b4c61921979ad3d3d1d19e338b1c4ba6a196b10c6400; /// @notice The address of the Grouping Module. IGroupingModule public immutable GROUPING_MODULE; @@ -82,7 +81,7 @@ contract GroupingWorkflow is licensingModule == address(0) || licenseRegistry == address(0) || pilTemplate == address(0) - ) revert Errors.GroupingWorkflow__ZeroAddressParam(); + ) revert Errors.GroupingWorkflows__ZeroAddressParam(); GROUPING_MODULE = IGroupingModule(groupingModule); GROUP_NFT = GroupNFT(groupNft); @@ -93,7 +92,7 @@ contract GroupingWorkflow is /// @dev Initializes the contract. /// @param accessManager The address of the protocol access manager. function initialize(address accessManager) external initializer { - if (accessManager == address(0)) revert Errors.GroupingWorkflow__ZeroAddressParam(); + if (accessManager == address(0)) revert Errors.GroupingWorkflows__ZeroAddressParam(); __AccessManaged_init(accessManager); __UUPSUpgradeable_init(); } @@ -101,8 +100,8 @@ contract GroupingWorkflow is /// @dev Sets the NFT contract beacon address. /// @param newNftContractBeacon The address of the new NFT contract beacon. function setNftContractBeacon(address newNftContractBeacon) external restricted { - if (newNftContractBeacon == address(0)) revert Errors.GroupingWorkflow__ZeroAddressParam(); - GroupingWorkflowStorage storage $ = _getGroupingWorkflowStorage(); + if (newNftContractBeacon == address(0)) revert Errors.GroupingWorkflows__ZeroAddressParam(); + GroupingWorkflowsStorage storage $ = _getGroupingWorkflowsStorage(); $.nftContractBeacon = newNftContractBeacon; } @@ -206,7 +205,7 @@ contract GroupingWorkflow is /// @notice Register a group IP with a group reward pool, register Programmable IP License Terms, /// attach it to the group IP, and add individual IPs to the group IP. - /// @dev ipIds must be have the same PIL terms as the group IP. + /// @dev ipIds must have the same PIL terms as the group IP. /// @param groupPool The address of the group reward pool. /// @param ipIds The IDs of the IPs to add to the newly registered group IP. /// @param groupIpTerms The PIL terms to be registered and attached to the newly registered group IP. @@ -236,10 +235,10 @@ contract GroupingWorkflow is // Upgrade // - /// @dev Returns the storage struct of GroupingWorkflow. - function _getGroupingWorkflowStorage() private pure returns (GroupingWorkflowStorage storage $) { + /// @dev Returns the storage struct of GroupingWorkflows. + function _getGroupingWorkflowsStorage() private pure returns (GroupingWorkflowsStorage storage $) { assembly { - $.slot := GroupingWorkflowStorageLocation + $.slot := GroupingWorkflowsStorageLocation } } diff --git a/contracts/SPGNFT.sol b/contracts/SPGNFT.sol index 7098619..dcd0dcf 100644 --- a/contracts/SPGNFT.sol +++ b/contracts/SPGNFT.sol @@ -31,7 +31,7 @@ contract SPGNFT is ISPGNFT, ERC721URIStorageUpgradeable, AccessControlUpgradeabl /// @dev The address of the SPG contract. address public immutable SPG_ADDRESS; - ///@dev The address of the GroupingWorkflow contract. + ///@dev The address of the GroupingWorkflows contract. address public immutable GROUPING_ADDRESS; /// @notice Modifier to restrict access to the SPG contract. @@ -42,11 +42,11 @@ contract SPGNFT is ISPGNFT, ERC721URIStorageUpgradeable, AccessControlUpgradeabl } /// @custom:oz-upgrades-unsafe-allow constructor - constructor(address spg, address groupingWorkflow) { - if (spg == address(0) || groupingWorkflow == address(0)) revert Errors.SPGNFT__ZeroAddressParam(); + constructor(address spg, address groupingWorkflows) { + if (spg == address(0) || groupingWorkflows == address(0)) revert Errors.SPGNFT__ZeroAddressParam(); SPG_ADDRESS = spg; - GROUPING_ADDRESS = groupingWorkflow; + GROUPING_ADDRESS = groupingWorkflows; _disableInitializers(); } diff --git a/contracts/StoryProtocolGateway.sol b/contracts/StoryProtocolGateway.sol index 0e9a11a..44f4533 100644 --- a/contracts/StoryProtocolGateway.sol +++ b/contracts/StoryProtocolGateway.sol @@ -163,7 +163,7 @@ contract StoryProtocolGateway is /// @param tokenId The ID of the NFT. /// @param ipMetadata OPTIONAL. The desired metadata for the newly registered IP. /// @param sigMetadata OPTIONAL. Signature data for setAll (metadata) for the IP via the Core Metadata Module. - /// @return ipId The ID of the newly registered IP + /// @return ipId The ID of the newly registered IP. function registerIp( address nftContract, uint256 tokenId, diff --git a/contracts/interfaces/IGroupingWorkflow.sol b/contracts/interfaces/IGroupingWorkflows.sol similarity index 98% rename from contracts/interfaces/IGroupingWorkflow.sol rename to contracts/interfaces/IGroupingWorkflows.sol index bb28bcc..c517516 100644 --- a/contracts/interfaces/IGroupingWorkflow.sol +++ b/contracts/interfaces/IGroupingWorkflows.sol @@ -5,8 +5,8 @@ import { PILTerms } from "@storyprotocol/core/interfaces/modules/licensing/IPILi import { IStoryProtocolGateway as ISPG } from "../interfaces/IStoryProtocolGateway.sol"; -/// @title Grouping Workflow Interface -interface IGroupingWorkflow { +/// @title Grouping Workflows Interface +interface IGroupingWorkflows { /// @notice Mint an NFT from a SPGNFT collection, register it with metadata as an IP, /// attach Programmable IP License Terms to the registered IP, and add it to a group IP. /// @dev Caller must have the minter role for the provided SPG NFT. diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index 9d3bdd0..2698c28 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -28,6 +28,6 @@ library Errors { /// @notice Caller is not one of the periphery contracts. error SPGNFT__CallerNotPeripheryContract(); - /// @notice Zero address provided as a param to the GroupingWorkflow. - error GroupingWorkflow__ZeroAddressParam(); + /// @notice Zero address provided as a param to the GroupingWorkflows. + error GroupingWorkflows__ZeroAddressParam(); } diff --git a/contracts/lib/LicensingHelper.sol b/contracts/lib/LicensingHelper.sol index df86149..9a6078e 100644 --- a/contracts/lib/LicensingHelper.sol +++ b/contracts/lib/LicensingHelper.sol @@ -42,7 +42,7 @@ library LicensingHelper { ILicensingModule(licensingModule).attachLicenseTerms(ipId, pilTemplate, licenseTermsId); } - /// @dev Collects license tokens from the caller. Assumes SPG has permission to transfer the license tokens. + /// @dev Collects license tokens from the caller. Assumes the periphery contract has permission to transfer the license tokens. /// @param licenseTokenIds The IDs of the license tokens to be collected. /// @param licenseToken The address of the license token contract. function collectLicenseTokens(uint256[] calldata licenseTokenIds, address licenseToken) internal { diff --git a/script/UpgradeSPGNFT.s.sol b/script/UpgradeSPGNFT.s.sol index b3aa6ed..e408c0a 100644 --- a/script/UpgradeSPGNFT.s.sol +++ b/script/UpgradeSPGNFT.s.sol @@ -8,7 +8,7 @@ import { Script } from "forge-std/Script.sol"; import { UpgradeableBeacon } from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; import { StoryProtocolGateway } from "../contracts/StoryProtocolGateway.sol"; -import { GroupingWorkflow } from "../contracts/GroupingWorkflow.sol"; +import { GroupingWorkflows } from "../contracts/GroupingWorkflows.sol"; import { SPGNFT } from "../contracts/SPGNFT.sol"; import { StoryProtocolPeripheryAddressManager } from "./utils/StoryProtocolPeripheryAddressManager.sol"; @@ -20,7 +20,7 @@ contract UpgradeSPGNFT is Script, StoryProtocolPeripheryAddressManager, Broadcas using StringUtil for uint256; StoryProtocolGateway private spg; - GroupingWorkflow private groupingWorkflow; + GroupingWorkflows private groupingWorkflows; SPGNFT private spgNftImpl; UpgradeableBeacon private spgNftBeacon; @@ -50,7 +50,7 @@ contract UpgradeSPGNFT is Script, StoryProtocolPeripheryAddressManager, Broadcas _writeAddress("SPGNFTBeacon", address(spgNftBeacon)); _predeploy("SPGNFTImpl"); - spgNftImpl = new SPGNFT(address(spg), address(groupingWorkflow)); + spgNftImpl = new SPGNFT(address(spg), address(groupingWorkflows)); _postdeploy("SPGNFTImpl", address(spgNftImpl)); } diff --git a/script/utils/BroadcastManager.s.sol b/script/utils/BroadcastManager.s.sol index 5bbcca5..318d6c1 100644 --- a/script/utils/BroadcastManager.s.sol +++ b/script/utils/BroadcastManager.s.sol @@ -3,8 +3,6 @@ pragma solidity ^0.8.23; import { Script } from "forge-std/Script.sol"; -import { StringUtil } from "./StringUtil.sol"; - contract BroadcastManager is Script { address public multisig; address public deployer; diff --git a/test/GroupingWorkflow.t.sol b/test/GroupingWorkflows.t.sol similarity index 89% rename from test/GroupingWorkflow.t.sol rename to test/GroupingWorkflows.t.sol index 9e7c4be..2e14f6c 100644 --- a/test/GroupingWorkflow.t.sol +++ b/test/GroupingWorkflows.t.sol @@ -10,7 +10,7 @@ import { ILicensingModule } from "@storyprotocol/core/interfaces/modules/licensi import { IStoryProtocolGateway as ISPG } from "../contracts/interfaces/IStoryProtocolGateway.sol"; -contract GroupingWorkflowTest is BaseTest { +contract GroupingWorkflowsTest is BaseTest { address internal groupId; function setUp() public override { @@ -48,7 +48,7 @@ contract GroupingWorkflowTest is BaseTest { _; } - function test_SPG_mintAndRegisterIpAndAddToGroup() + function test_GroupingWorkflows_mintAndRegisterIpAndAttachPILTermsAndAddToGroup() public withCollection whenCallerHasMinterRole @@ -59,7 +59,7 @@ contract GroupingWorkflowTest is BaseTest { (bytes memory sigAddToGroup, bytes32 expectedState, ) = _getSetPermissionSigForPeriphery({ ipId: groupId, - to: address(groupingWorkflow), + to: address(groupingWorkflows), module: address(groupingModule), selector: IGroupingModule.addIp.selector, deadline: deadline, @@ -67,7 +67,7 @@ contract GroupingWorkflowTest is BaseTest { signerPk: alicePk }); - (address ipId, uint256 tokenId) = groupingWorkflow.mintAndRegisterIpAndAttachPILTermsAndAddToGroup({ + (address ipId, uint256 tokenId) = groupingWorkflows.mintAndRegisterIpAndAttachPILTermsAndAddToGroup({ spgNftContract: address(nftContract), groupId: groupId, recipient: caller, @@ -89,7 +89,7 @@ contract GroupingWorkflowTest is BaseTest { assertEq(licenseTermsId, 1); } - function test_SPG_registerIpAndAddToGroup() + function test_GroupingWorkflows_registerIpAndAttachPILTermsAndAddToGroup() public withCollection whenCallerHasMinterRole @@ -103,7 +103,7 @@ contract GroupingWorkflowTest is BaseTest { (bytes memory sigMetadataAndAttach, , ) = _getSetBatchPermissionSigForPeriphery({ ipId: expectedIpId, - permissionList: _getMetadataAndAttachTermsPermissionList(expectedIpId, address(groupingWorkflow)), + permissionList: _getMetadataAndAttachTermsPermissionList(expectedIpId, address(groupingWorkflows)), deadline: deadline, state: bytes32(0), signerPk: alicePk @@ -111,7 +111,7 @@ contract GroupingWorkflowTest is BaseTest { (bytes memory sigAddToGroup, , ) = _getSetPermissionSigForPeriphery({ ipId: groupId, - to: address(groupingWorkflow), + to: address(groupingWorkflows), module: address(groupingModule), selector: IGroupingModule.addIp.selector, deadline: deadline, @@ -119,7 +119,7 @@ contract GroupingWorkflowTest is BaseTest { signerPk: alicePk }); - address ipId = groupingWorkflow.registerIpAndAttachPILTermsAndAddToGroup({ + address ipId = groupingWorkflows.registerIpAndAttachPILTermsAndAddToGroup({ nftContract: address(nftContract), tokenId: tokenId, groupId: groupId, @@ -145,7 +145,11 @@ contract GroupingWorkflowTest is BaseTest { assertEq(licenseTermsId, 1); } - function test_SPG_registerGroupAndAddIps() public withCollection whenCallerHasMinterRole { + function test_GroupingWorkflows_registerGroupAndAttachPILTermsAndAddIps() + public + withCollection + whenCallerHasMinterRole + { mockToken.mint(address(caller), 1000 * 10 * 10 ** mockToken.decimals()); mockToken.approve(address(nftContract), 1000 * 10 * 10 ** mockToken.decimals()); @@ -167,7 +171,7 @@ contract GroupingWorkflowTest is BaseTest { } uint256 groupLicenseTermsId; - (groupId, groupLicenseTermsId) = groupingWorkflow.registerGroupAndAttachPILTermsAndAddIps( + (groupId, groupLicenseTermsId) = groupingWorkflows.registerGroupAndAttachPILTermsAndAddIps( address(rewardPool), ipIds, PILFlavors.nonCommercialSocialRemixing() diff --git a/test/SPGNFT.t.sol b/test/SPGNFT.t.sol index c44ab6e..d1edbf0 100644 --- a/test/SPGNFT.t.sol +++ b/test/SPGNFT.t.sol @@ -36,7 +36,7 @@ contract SPGNFTTest is BaseTest { } function test_SPGNFT_initialize() public { - address spgNftImpl = address(new SPGNFT(address(spg), address(groupingWorkflow))); + address spgNftImpl = address(new SPGNFT(address(spg), address(groupingWorkflows))); address NFT_CONTRACT_BEACON = address(new UpgradeableBeacon(spgNftImpl, deployer)); ISPGNFT anotherNftContract = ISPGNFT(address(new BeaconProxy(NFT_CONTRACT_BEACON, ""))); @@ -57,7 +57,7 @@ contract SPGNFTTest is BaseTest { } function test_SPGNFT_initialize_revert_zeroParams() public { - address spgNftImpl = address(new SPGNFT(address(spg), address(groupingWorkflow))); + address spgNftImpl = address(new SPGNFT(address(spg), address(groupingWorkflows))); address NFT_CONTRACT_BEACON = address(new UpgradeableBeacon(spgNftImpl, deployer)); nftContract = ISPGNFT(address(new BeaconProxy(NFT_CONTRACT_BEACON, ""))); diff --git a/test/utils/BaseTest.t.sol b/test/utils/BaseTest.t.sol index 10648b9..29a560f 100644 --- a/test/utils/BaseTest.t.sol +++ b/test/utils/BaseTest.t.sol @@ -35,7 +35,7 @@ import { ICoreMetadataModule } from "@storyprotocol/core/interfaces/modules/meta import { StoryProtocolGateway } from "../../contracts/StoryProtocolGateway.sol"; import { IStoryProtocolGateway as ISPG } from "../../contracts/interfaces/IStoryProtocolGateway.sol"; -import { GroupingWorkflow } from "../../contracts/GroupingWorkflow.sol"; +import { GroupingWorkflows } from "../../contracts/GroupingWorkflows.sol"; import { SPGNFT } from "../../contracts/SPGNFT.sol"; import { ISPGNFT } from "../../contracts/interfaces/ISPGNFT.sol"; import { TestProxyHelper } from "./TestProxyHelper.t.sol"; @@ -74,7 +74,7 @@ contract BaseTest is Test { StoryProtocolGateway internal spg; SPGNFT internal spgNftImpl; UpgradeableBeacon internal spgNftBeacon; - GroupingWorkflow internal groupingWorkflow; + GroupingWorkflows internal groupingWorkflows; MockERC20 internal mockToken; MockIPGraph internal ipGraph = MockIPGraph(address(0x1A)); @@ -509,7 +509,7 @@ contract BaseTest is Test { impl = address(0); // Make sure we don't deploy wrong impl impl = address( - new GroupingWorkflow( + new GroupingWorkflows( address(accessController), address(coreMetadataModule), address(groupingModule), @@ -521,19 +521,19 @@ contract BaseTest is Test { ) ); - groupingWorkflow = GroupingWorkflow( + groupingWorkflows = GroupingWorkflows( TestProxyHelper.deployUUPSProxy( create3Deployer, - _getSalt(type(GroupingWorkflow).name), + _getSalt(type(GroupingWorkflows).name), impl, - abi.encodeCall(GroupingWorkflow.initialize, address(protocolAccessManager)) + abi.encodeCall(GroupingWorkflows.initialize, address(protocolAccessManager)) ) ); spgNftImpl = SPGNFT( create3Deployer.deploy( _getSalt(type(SPGNFT).name), - abi.encodePacked(type(SPGNFT).creationCode, abi.encode(address(spg), address(groupingWorkflow))) + abi.encodePacked(type(SPGNFT).creationCode, abi.encode(address(spg), address(groupingWorkflows))) ) ); @@ -545,7 +545,7 @@ contract BaseTest is Test { ); spg.setNftContractBeacon(address(spgNftBeacon)); - groupingWorkflow.setNftContractBeacon(address(spgNftBeacon)); + groupingWorkflows.setNftContractBeacon(address(spgNftBeacon)); // bytes4[] memory selectors = new bytes4[](1); // selectors[0] = UUPSUpgradeable.upgradeToAndCall.selector; diff --git a/yarn.lock b/yarn.lock index cc280b5..506f2ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -996,9 +996,9 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^1.0.5: version "1.0.5" @@ -2352,9 +2352,9 @@ solhint@^4.1.1: prettier "^2.8.3" solidity-coverage@^0.8.6: - version "0.8.12" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.12.tgz#c4fa2f64eff8ada7a1387b235d6b5b0e6c6985ed" - integrity sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw== + version "0.8.13" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.13.tgz#8eeada2e82ae19d25568368aa782a2baad0e0ce7" + integrity sha512-RiBoI+kF94V3Rv0+iwOj3HQVSqNzA9qm/qDP1ZDXK5IX0Cvho1qiz8hAXTsAo6KOIUeP73jfscq0KlLqVxzGWA== dependencies: "@ethersproject/abi" "^5.0.9" "@solidity-parser/parser" "^0.18.0" @@ -2595,9 +2595,9 @@ typical@^5.2.0: integrity sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg== uglify-js@^3.1.4: - version "3.19.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.2.tgz#319ae26a5fbd18d03c7dc02496cfa1d6f1cd4307" - integrity sha512-S8KA6DDI47nQXJSi2ctQ629YzwOVs+bQML6DAtvy0wgNdpi+0ySpQK0g2pxBq2xfF2z3YCscu7NNA8nXT9PlIQ== + version "3.19.3" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" + integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== undici-types@~6.19.2: version "6.19.8"