Skip to content

Commit

Permalink
feat(deriv): adopt setBatchPermission
Browse files Browse the repository at this point in the history
  • Loading branch information
sebsadface committed Dec 20, 2024
1 parent d8930f9 commit 64b7840
Show file tree
Hide file tree
Showing 10 changed files with 214 additions and 217 deletions.
14 changes: 6 additions & 8 deletions contracts/interfaces/workflows/IDerivativeWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,15 @@ interface IDerivativeWorkflows {
/// @param tokenId The ID of the NFT.
/// @param derivData The derivative data to be used for registerDerivative.
/// @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.
/// @param sigRegister Signature data for registerDerivative for the IP via the Licensing Module.
/// @param sigMetadataAndRegister OPTIONAL. Signature data for setAll (metadata) for the IP via the Core Metadata Module
/// and registerDerivative for the IP via the Licensing Module.
/// @return ipId The ID of the newly registered IP.
function registerIpAndMakeDerivative(
address nftContract,
uint256 tokenId,
WorkflowStructs.MakeDerivative calldata derivData,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadata,
WorkflowStructs.SignatureData calldata sigRegister
WorkflowStructs.SignatureData calldata sigMetadataAndRegister
) external returns (address ipId);

/// @notice Mint an NFT from a SPGNFT collection and register it as a derivative IP using license tokens.
Expand Down Expand Up @@ -70,8 +69,8 @@ interface IDerivativeWorkflows {
/// @param royaltyContext The context for royalty module, should be empty for Royalty Policy LAP.
/// @param maxRts The maximum number of royalty tokens that can be distributed to the external royalty policies.
/// @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.
/// @param sigRegister Signature data for registerDerivativeWithLicenseTokens for the IP via the Licensing Module.
/// @param sigMetadataAndRegister Signature data for setAll (metadata) for the IP via the Core Metadata Module
/// and registerDerivativeWithLicenseTokens for the IP via the Licensing Module.
/// @return ipId The ID of the newly registered IP.
function registerIpAndMakeDerivativeWithLicenseTokens(
address nftContract,
Expand All @@ -80,8 +79,7 @@ interface IDerivativeWorkflows {
bytes calldata royaltyContext,
uint32 maxRts,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadata,
WorkflowStructs.SignatureData calldata sigRegister
WorkflowStructs.SignatureData calldata sigMetadataAndRegister
) external returns (address ipId);

////////////////////////////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,4 @@ interface IRoyaltyTokenDistributionWorkflows {
WorkflowStructs.SignatureData calldata sigMetadata,
WorkflowStructs.SignatureData calldata sigAttach
) external returns (address ipId, uint256[] memory licenseTermsIds, address ipRoyaltyVault);

}
74 changes: 37 additions & 37 deletions contracts/workflows/DerivativeWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import { ICoreMetadataModule } from "@storyprotocol/core/interfaces/modules/metadata/ICoreMetadataModule.sol";
import { ILicenseToken } from "@storyprotocol/core/interfaces/ILicenseToken.sol";
import { ILicensingModule } from "@storyprotocol/core/interfaces/modules/licensing/ILicensingModule.sol";
import { IRoyaltyModule } from "@storyprotocol/core/interfaces/modules/royalty/IRoyaltyModule.sol";
Expand Down Expand Up @@ -151,33 +152,33 @@ contract DerivativeWorkflows is
/// @param tokenId The ID of the NFT.
/// @param derivData The derivative data to be used for registerDerivative.
/// @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.
/// @param sigRegister Signature data for registerDerivative for the IP via the Licensing Module.
/// @param sigMetadataAndRegister OPTIONAL. Signature data for setAll (metadata) for the IP via the Core Metadata
/// Module and registerDerivative for the IP via the Licensing Module.
/// @return ipId The ID of the newly registered IP.
function registerIpAndMakeDerivative(
address nftContract,
uint256 tokenId,
WorkflowStructs.MakeDerivative calldata derivData,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadata,
WorkflowStructs.SignatureData calldata sigRegister
WorkflowStructs.SignatureData calldata sigMetadataAndRegister
) external returns (address ipId) {
ipId = IP_ASSET_REGISTRY.register(block.chainid, nftContract, tokenId);
MetadataHelper.setMetadataWithSig(
ipId,
address(CORE_METADATA_MODULE),
address(ACCESS_CONTROLLER),
ipMetadata,
sigMetadata
);

PermissionHelper.setPermissionForModule(
ipId,
address(LICENSING_MODULE),
address(ACCESS_CONTROLLER),
ILicensingModule.registerDerivative.selector,
sigRegister
);
address[] memory modules = new address[](2);
bytes4[] memory selectors = new bytes4[](2);
modules[0] = address(CORE_METADATA_MODULE);
modules[1] = address(LICENSING_MODULE);
selectors[0] = ICoreMetadataModule.setAll.selector;
selectors[1] = ILicensingModule.registerDerivative.selector;
PermissionHelper.setBatchPermissionForModules({
ipId: ipId,
accessController: address(ACCESS_CONTROLLER),
modules: modules,
selectors: selectors,
sigData: sigMetadataAndRegister
});

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

LicensingHelper.collectMintFeesAndMakeDerivative(
ipId,
Expand Down Expand Up @@ -233,8 +234,8 @@ contract DerivativeWorkflows is
/// @param royaltyContext The context for royalty module, should be empty for Royalty Policy LAP.
/// @param maxRts The maximum number of royalty tokens that can be distributed to the external royalty policies.
/// @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.
/// @param sigRegister Signature data for registerDerivativeWithLicenseTokens for the IP via the Licensing Module.
/// @param sigMetadataAndRegister Signature data for setAll (metadata) for the IP via the Core Metadata Module
/// and registerDerivativeWithLicenseTokens for the IP via the Licensing Module.
/// @return ipId The ID of the newly registered IP.
function registerIpAndMakeDerivativeWithLicenseTokens(
address nftContract,
Expand All @@ -243,27 +244,26 @@ contract DerivativeWorkflows is
bytes calldata royaltyContext,
uint32 maxRts,
WorkflowStructs.IPMetadata calldata ipMetadata,
WorkflowStructs.SignatureData calldata sigMetadata,
WorkflowStructs.SignatureData calldata sigRegister
WorkflowStructs.SignatureData calldata sigMetadataAndRegister
) external returns (address ipId) {
_collectLicenseTokens(licenseTokenIds, address(LICENSE_TOKEN));

ipId = IP_ASSET_REGISTRY.register(block.chainid, nftContract, tokenId);
MetadataHelper.setMetadataWithSig(
ipId,
address(CORE_METADATA_MODULE),
address(ACCESS_CONTROLLER),
ipMetadata,
sigMetadata
);

PermissionHelper.setPermissionForModule(
ipId,
address(LICENSING_MODULE),
address(ACCESS_CONTROLLER),
ILicensingModule.registerDerivativeWithLicenseTokens.selector,
sigRegister
);
address[] memory modules = new address[](2);
bytes4[] memory selectors = new bytes4[](2);
modules[0] = address(CORE_METADATA_MODULE);
modules[1] = address(LICENSING_MODULE);
selectors[0] = ICoreMetadataModule.setAll.selector;
selectors[1] = ILicensingModule.registerDerivativeWithLicenseTokens.selector;
PermissionHelper.setBatchPermissionForModules({
ipId: ipId,
accessController: address(ACCESS_CONTROLLER),
modules: modules,
selectors: selectors,
sigData: sigMetadataAndRegister
});

MetadataHelper.setMetadata(ipId, address(CORE_METADATA_MODULE), ipMetadata);
LICENSING_MODULE.registerDerivativeWithLicenseTokens(ipId, licenseTokenIds, royaltyContext, maxRts);
}

Expand Down
31 changes: 31 additions & 0 deletions test/integration/BaseIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,37 @@ contract BaseIntegration is Test, Script, StoryProtocolCoreAddressManager, Story
/*//////////////////////////////////////////////////////////////////////////
HELPERS
//////////////////////////////////////////////////////////////////////////*/
/// @dev Get the permission list for setting metadata and registering a derivative for the IP.
/// @param ipId The ID of the IP that the permissions are for.
/// @param to The address of the periphery contract to receive the permission.
/// @return permissionList The list of permissions for setting metadata and registering a derivative.
function _getMetadataAndDerivativeRegistrationPermissionList(
address ipId,
address to,
bool withLicenseToken
) internal view returns (AccessPermission.Permission[] memory permissionList) {
address[] memory modules = new address[](2);
bytes4[] memory selectors = new bytes4[](2);
permissionList = new AccessPermission.Permission[](2);
modules[0] = coreMetadataModuleAddr;
modules[1] = licensingModuleAddr;
selectors[0] = ICoreMetadataModule.setAll.selector;
if (withLicenseToken) {
selectors[1] = ILicensingModule.registerDerivativeWithLicenseTokens.selector;
} else {
selectors[1] = ILicensingModule.registerDerivative.selector;
}
for (uint256 i = 0; i < 2; i++) {
permissionList[i] = AccessPermission.Permission({
ipAccount: ipId,
signer: to,
to: modules[i],
func: selectors[i],
permission: AccessPermission.ALLOW
});
}
}

/// @dev Get the permission list for attaching license terms and setting licensing config for the IP.
/// @param ipId The ID of the IP that the permissions are for.
/// @param to The address of the periphery contract to receive the permission.
Expand Down
79 changes: 24 additions & 55 deletions test/integration/workflows/DerivativeIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,26 +100,18 @@ contract DerivativeIntegration is BaseIntegration {

uint256 deadline = block.timestamp + 1000;

(bytes memory sigMetadata, bytes32 sigRegisterState, ) = _getSetPermissionSigForPeriphery({
(bytes memory signatureMetadataAndRegister, bytes32 expectedState, ) = _getSetBatchPermissionSigForPeriphery({
ipId: childIpId,
to: derivativeWorkflowsAddr,
module: coreMetadataModuleAddr,
selector: ICoreMetadataModule.setAll.selector,
permissionList: _getMetadataAndDerivativeRegistrationPermissionList(
childIpId,
address(derivativeWorkflows),
false
),
deadline: deadline,
state: bytes32(0),
signerSk: testSenderSk
});

(bytes memory sigRegister, bytes32 expectedState, ) = _getSetPermissionSigForPeriphery({
ipId: childIpId,
to: derivativeWorkflowsAddr,
module: licensingModuleAddr,
selector: ILicensingModule.registerDerivative.selector,
deadline: deadline,
state: sigRegisterState,
signerSk: testSenderSk
});

StoryUSD.mint(testSender, testMintFee);
StoryUSD.approve(derivativeWorkflowsAddr, testMintFee); // for derivative minting fee
derivativeWorkflows.registerIpAndMakeDerivative({
Expand All @@ -135,15 +127,10 @@ contract DerivativeIntegration is BaseIntegration {
maxRevenueShare: 0
}),
ipMetadata: testIpMetadata,
sigMetadata: WorkflowStructs.SignatureData({
signer: testSender,
deadline: deadline,
signature: sigMetadata
}),
sigRegister: WorkflowStructs.SignatureData({
sigMetadataAndRegister: WorkflowStructs.SignatureData({
signer: testSender,
deadline: deadline,
signature: sigRegister
signature: signatureMetadataAndRegister
})
});

Expand Down Expand Up @@ -255,38 +242,17 @@ contract DerivativeIntegration is BaseIntegration {
licenseTokenIds[0] = startLicenseTokenId;
licenseToken.approve(derivativeWorkflowsAddr, startLicenseTokenId);

WorkflowStructs.SignatureData memory sigMetadata;
WorkflowStructs.SignatureData memory sigRegister;
{
(bytes memory signatureMetadata, bytes32 sigRegisterState, ) = _getSetPermissionSigForPeriphery({
ipId: childIpId,
to: derivativeWorkflowsAddr,
module: coreMetadataModuleAddr,
selector: ICoreMetadataModule.setAll.selector,
deadline: deadline,
state: bytes32(0),
signerSk: testSenderSk
});
(bytes memory signatureRegister, bytes32 expectedState, ) = _getSetPermissionSigForPeriphery({
ipId: childIpId,
to: derivativeWorkflowsAddr,
module: licensingModuleAddr,
selector: ILicensingModule.registerDerivativeWithLicenseTokens.selector,
deadline: deadline,
state: sigRegisterState,
signerSk: testSenderSk
});
sigMetadata = WorkflowStructs.SignatureData({
signer: testSender,
deadline: deadline,
signature: signatureMetadata
});
sigRegister = WorkflowStructs.SignatureData({
signer: testSender,
deadline: deadline,
signature: signatureRegister
});
}
(bytes memory signatureMetadataAndRegister, bytes32 expectedState, ) = _getSetBatchPermissionSigForPeriphery({
ipId: childIpId,
permissionList: _getMetadataAndDerivativeRegistrationPermissionList(
childIpId,
address(derivativeWorkflows),
true
),
deadline: deadline,
state: bytes32(0),
signerSk: testSenderSk
});

derivativeWorkflows.registerIpAndMakeDerivativeWithLicenseTokens({
nftContract: address(spgNftContract),
Expand All @@ -295,8 +261,11 @@ contract DerivativeIntegration is BaseIntegration {
royaltyContext: "",
maxRts: revShare,
ipMetadata: testIpMetadata,
sigMetadata: sigMetadata,
sigRegister: sigRegister
sigMetadataAndRegister: WorkflowStructs.SignatureData({
signer: testSender,
deadline: deadline,
signature: signatureMetadataAndRegister
})
});

assertTrue(ipAssetRegistry.isRegistered(childIpId));
Expand Down
Loading

0 comments on commit 64b7840

Please sign in to comment.