Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(deriv): restore v1.2 compatibility to GroupingWorkflows #148

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions contracts/interfaces/workflows/IGroupingWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,64 @@ interface IGroupingWorkflows {
address[] calldata currencyTokens,
address[] calldata memberIpIds
) external returns (uint256[] memory collectedRoyalties);

////////////////////////////////////////////////////////////////////////////
// DEPRECATED, WILL BE REMOVED IN V1.4 //
////////////////////////////////////////////////////////////////////////////

/// @notice Mint an NFT from a SPGNFT collection, register it with metadata as an IP,
/// attach license terms to the registered IP, and add it to a group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function mintAndRegisterIpAndAttachLicenseAndAddToGroup(
address spgNftContract,
address groupId,
address recipient,
address licenseTemplate,
uint256 licenseTermsId,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigAddToGroup
) external returns (address ipId, uint256 tokenId);

/// @notice Register an NFT as IP with metadata, attach license terms to the registered IP,
/// and add it to a group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
/// @dev UPDATE REQUIRED: The sigMetadataAndAttachAndConfig permission signature data must be updated and include permissions for
/// metadata setting, license attachment, and licensing configuration permissions
function registerIpAndAttachLicenseAndAddToGroup(
address nftContract,
uint256 tokenId,
address groupId,
address licenseTemplate,
uint256 licenseTermsId,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadataAndAttachAndConfig,
WorkflowStructs.SignatureData calldata sigAddToGroup
) external returns (address ipId);

/// @notice Register a group IP with a group reward pool and attach license terms to the group IP
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function registerGroupAndAttachLicense(
address groupPool,
address licenseTemplate,
uint256 licenseTermsId
) external returns (address groupId);

/// @notice Register a group IP with a group reward pool, attach license terms to the group IP,
/// and add individual IPs to the group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function registerGroupAndAttachLicenseAndAddIps(
address groupPool,
address[] calldata ipIds,
address licenseTemplate,
uint256 licenseTermsId
) external returns (address groupId);

/// @notice Collect royalties for the entire group and distribute the rewards to each member IP's royalty vault
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function collectRoyaltiesAndClaimReward(
address groupIpId,
address[] calldata currencyTokens,
uint256[] calldata groupSnapshotIds,
address[] calldata memberIpIds
) external returns (uint256[] memory collectedRoyalties);
}
220 changes: 219 additions & 1 deletion contracts/workflows/GroupingWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils

import { ICoreMetadataModule } from "@storyprotocol/core/interfaces/modules/metadata/ICoreMetadataModule.sol";
import { IGroupingModule } from "@storyprotocol/core/interfaces/modules/grouping/IGroupingModule.sol";
import { IGroupIPAssetRegistry } from "@storyprotocol/core/interfaces/registries/IGroupIPAssetRegistry.sol";
import { ILicensingModule } from "@storyprotocol/core/interfaces/modules/licensing/ILicensingModule.sol";
import { IPILicenseTemplate, PILTerms } from "@storyprotocol/core/interfaces/modules/licensing/IPILicenseTemplate.sol";
import { GroupNFT } from "@storyprotocol/core/GroupNFT.sol";
import { Licensing } from "@storyprotocol/core/lib/Licensing.sol";
import { RoyaltyModule } from "@storyprotocol/core/modules/royalty/RoyaltyModule.sol";

import { BaseWorkflow } from "../BaseWorkflow.sol";
Expand Down Expand Up @@ -315,7 +318,7 @@ contract GroupingWorkflows is
/// @dev Attaches licenses to the given IP and sets their licensing configurations.
/// @param ipId The ID of the IP.
/// @param licensesData The data of the licenses and their configurations to be attached to the IP.
function _attachLicensesAndSetConfigs(address ipId, WorkflowStructs.LicenseData[] calldata licensesData) private {
function _attachLicensesAndSetConfigs(address ipId, WorkflowStructs.LicenseData[] memory licensesData) private {
for (uint256 i; i < licensesData.length; i++) {
LicensingHelper.attachLicenseTermsAndSetConfigs(
ipId,
Expand All @@ -341,4 +344,219 @@ contract GroupingWorkflows is
/// @dev Hook to authorize the upgrade according to UUPSUpgradeable
/// @param newImplementation The address of the new implementation
function _authorizeUpgrade(address newImplementation) internal override restricted {}

////////////////////////////////////////////////////////////////////////////
// DEPRECATED, WILL BE REMOVED IN V1.4 //
////////////////////////////////////////////////////////////////////////////

/// @notice Mint an NFT from a SPGNFT collection, register it with metadata as an IP, attach
/// license terms to the registered IP, and add it to a group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
sebsadface marked this conversation as resolved.
Show resolved Hide resolved
function mintAndRegisterIpAndAttachLicenseAndAddToGroup(
address spgNftContract,
address groupId,
address recipient,
address licenseTemplate,
uint256 licenseTermsId,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigAddToGroup
) external onlyMintAuthorized(spgNftContract) returns (address ipId, uint256 tokenId) {
tokenId = ISPGNFT(spgNftContract).mintByPeriphery({
to: address(this),
payer: msg.sender,
nftMetadataURI: ipMetadata.nftMetadataURI,
nftMetadataHash: "",
allowDuplicates: true
});
ipId = IP_ASSET_REGISTRY.register(block.chainid, spgNftContract, tokenId);
MetadataHelper.setMetadata(ipId, address(CORE_METADATA_MODULE), ipMetadata);

_prepConfigAndAttachLicenseAndSetConfig(ipId, groupId, licenseTemplate, licenseTermsId);

PermissionHelper.setPermissionForModule(
groupId,
address(GROUPING_MODULE),
address(ACCESS_CONTROLLER),
IGroupingModule.addIp.selector,
sigAddToGroup
);

address[] memory ipIds = new address[](1);
ipIds[0] = ipId;
GROUPING_MODULE.addIp(groupId, ipIds);

ISPGNFT(spgNftContract).safeTransferFrom(address(this), recipient, tokenId, "");
}

/// @notice Register an NFT as IP with metadata, attach license terms to the registered IP,
/// and add it to a group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
/// @dev UPDATE REQUIRED: The sigMetadataAndAttachAndConfig permission signature data must be updated and include permissions for
/// metadata setting, license attachment, and licensing configuration permissions
function registerIpAndAttachLicenseAndAddToGroup(
address nftContract,
uint256 tokenId,
address groupId,
address licenseTemplate,
uint256 licenseTermsId,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadataAndAttachAndConfig,
WorkflowStructs.SignatureData calldata sigAddToGroup
) external returns (address ipId) {
ipId = IP_ASSET_REGISTRY.register(block.chainid, nftContract, tokenId);

address[] memory modules = new address[](3);
bytes4[] memory selectors = new bytes4[](3);
modules[0] = address(CORE_METADATA_MODULE);
modules[1] = address(LICENSING_MODULE);
modules[2] = address(LICENSING_MODULE);
selectors[0] = ICoreMetadataModule.setAll.selector;
selectors[1] = ILicensingModule.attachLicenseTerms.selector;
selectors[2] = ILicensingModule.setLicensingConfig.selector;

PermissionHelper.setBatchPermissionForModules(
ipId,
address(ACCESS_CONTROLLER),
modules,
selectors,
sigMetadataAndAttachAndConfig
);

MetadataHelper.setMetadata(ipId, address(CORE_METADATA_MODULE), ipMetadata);

_prepConfigAndAttachLicenseAndSetConfig(ipId, groupId, licenseTemplate, licenseTermsId);

PermissionHelper.setPermissionForModule(
groupId,
address(GROUPING_MODULE),
address(ACCESS_CONTROLLER),
IGroupingModule.addIp.selector,
sigAddToGroup
);

address[] memory ipIds = new address[](1);
ipIds[0] = ipId;
GROUPING_MODULE.addIp(groupId, ipIds);
}

/// @notice Register a group IP with a group reward pool and attach license terms to the group IP
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function registerGroupAndAttachLicense(
address groupPool,
address licenseTemplate,
uint256 licenseTermsId
) external returns (address groupId) {
groupId = GROUPING_MODULE.registerGroup(groupPool);

_prepConfigAndAttachLicenseAndSetConfigForGroup(groupId, groupPool, licenseTemplate, licenseTermsId);

GROUP_NFT.safeTransferFrom(address(this), msg.sender, GROUP_NFT.totalSupply() - 1);
}

/// @notice Register a group IP with a group reward pool, attach license terms to the group IP,
/// and add individual IPs to the group IP.
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function registerGroupAndAttachLicenseAndAddIps(
address groupPool,
address[] calldata ipIds,
address licenseTemplate,
uint256 licenseTermsId
) external returns (address groupId) {
groupId = GROUPING_MODULE.registerGroup(groupPool);

_prepConfigAndAttachLicenseAndSetConfigForGroup(groupId, groupPool, licenseTemplate, licenseTermsId);

GROUPING_MODULE.addIp(groupId, ipIds);

GROUP_NFT.safeTransferFrom(address(this), msg.sender, GROUP_NFT.totalSupply() - 1);
}

/// @notice Collect royalties for the entire group and distribute the rewards to each member IP's royalty vault
/// @notice THIS VERSION OF THE FUNCTION IS DEPRECATED, WILL BE REMOVED IN V1.4
function collectRoyaltiesAndClaimReward(
address groupIpId,
address[] calldata currencyTokens,
uint256[] calldata groupSnapshotIds,
address[] calldata memberIpIds
) external returns (uint256[] memory collectedRoyalties) {
(address groupLicenseTemplate, uint256 groupLicenseTermsId) = LICENSE_REGISTRY.getAttachedLicenseTerms(
groupIpId,
0
);

for (uint256 i = 0; i < memberIpIds.length; i++) {
// check if given member IPs already have a royalty vault
if (ROYALTY_MODULE.ipRoyaltyVaults(memberIpIds[i]) == address(0)) {
// mint license tokens to the member IPs if they don't have a royalty vault
LICENSING_MODULE.mintLicenseTokens({
licensorIpId: memberIpIds[i],
licenseTemplate: groupLicenseTemplate,
licenseTermsId: groupLicenseTermsId,
amount: 1,
receiver: msg.sender,
royaltyContext: "",
maxMintingFee: 0,
maxRevenueShare: 0
});
}
}

collectedRoyalties = new uint256[](currencyTokens.length);
for (uint256 i = 0; i < currencyTokens.length; i++) {
if (currencyTokens[i] == address(0)) revert Errors.GroupingWorkflows__ZeroAddressParam();
collectedRoyalties[i] = GROUPING_MODULE.collectRoyalties(groupIpId, currencyTokens[i]);
GROUPING_MODULE.claimReward(groupIpId, currencyTokens[i], memberIpIds);
}
}

function _prepConfigAndAttachLicenseAndSetConfig(
address ipId,
address groupId,
address licenseTemplate,
uint256 licenseTermsId
) private {
PILTerms memory terms = IPILicenseTemplate(licenseTemplate).getLicenseTerms(licenseTermsId);
WorkflowStructs.LicenseData[] memory licensesData = new WorkflowStructs.LicenseData[](1);
licensesData[0] = WorkflowStructs.LicenseData({
licenseTemplate: licenseTemplate,
licenseTermsId: licenseTermsId,
licensingConfig: Licensing.LicensingConfig({
isSet: true,
mintingFee: terms.defaultMintingFee,
licensingHook: address(0),
hookData: "",
commercialRevShare: terms.commercialRevShare,
disabled: false,
expectMinimumGroupRewardShare: 0,
expectGroupRewardPool: IGroupIPAssetRegistry(address(IP_ASSET_REGISTRY)).getGroupRewardPool(groupId)
})
});
_attachLicensesAndSetConfigs(ipId, licensesData);
}

function _prepConfigAndAttachLicenseAndSetConfigForGroup(
address groupId,
address groupRewardPool,
address licenseTemplate,
uint256 licenseTermsId
) private {
PILTerms memory terms = IPILicenseTemplate(licenseTemplate).getLicenseTerms(licenseTermsId);
Licensing.LicensingConfig memory licensingConfig = Licensing.LicensingConfig({
isSet: true,
mintingFee: terms.defaultMintingFee,
licensingHook: address(0),
hookData: "",
commercialRevShare: terms.commercialRevShare,
disabled: false,
expectMinimumGroupRewardShare: 0,
expectGroupRewardPool: address(0)
});
LicensingHelper.attachLicenseTermsAndSetConfigs(
groupId,
address(LICENSING_MODULE),
licenseTemplate,
licenseTermsId,
licensingConfig
);
}
}
12 changes: 10 additions & 2 deletions test/integration/workflows/GroupingIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,11 @@ contract GroupingIntegration is BaseIntegration {
bytes[] memory data = new bytes[](numCalls);
for (uint256 i = 0; i < numCalls; i++) {
data[i] = abi.encodeWithSelector(
groupingWorkflows.mintAndRegisterIpAndAttachLicenseAndAddToGroup.selector,
bytes4(
keccak256(
"mintAndRegisterIpAndAttachLicenseAndAddToGroup(address,address,address,(address,uint256,(bool,uint256,address,bytes,uint32,bool,uint32,address))[],(string,bytes32,string,bytes32),(address,uint256,bytes),bool)"
)
),
address(spgNftContract),
groupId,
testSender,
Expand Down Expand Up @@ -414,7 +418,11 @@ contract GroupingIntegration is BaseIntegration {
bytes[] memory data = new bytes[](numCalls);
for (uint256 i = 0; i < numCalls; i++) {
data[i] = abi.encodeWithSelector(
groupingWorkflows.registerIpAndAttachLicenseAndAddToGroup.selector,
bytes4(
keccak256(
"registerIpAndAttachLicenseAndAddToGroup(address,uint256,address,(address,uint256,(bool,uint256,address,bytes,uint32,bool,uint32,address))[],(string,bytes32,string,bytes32),(address,uint256,bytes),(address,uint256,bytes))"
)
),
address(spgNftContract),
tokenIds[i],
groupId,
Expand Down
Loading
Loading