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

opt(licensing): remove hasIpAttachedLicenseTerms check #84

Merged
merged 1 commit into from
Sep 30, 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
16 changes: 11 additions & 5 deletions contracts/lib/LicensingHelper.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import { ILicenseRegistry } from "@storyprotocol/core/interfaces/registries/ILicenseRegistry.sol";
import { Errors as CoreErrors } from "@storyprotocol/core/lib/Errors.sol";
import { ILicensingModule } from "@storyprotocol/core/interfaces/modules/licensing/ILicensingModule.sol";
import { IPILicenseTemplate, PILTerms } from "@storyprotocol/core/interfaces/modules/licensing/IPILicenseTemplate.sol";

Expand Down Expand Up @@ -40,9 +40,15 @@ library LicensingHelper {
address licenseTemplate,
uint256 licenseTermsId
) internal {
// Returns if license terms are already attached.
if (ILicenseRegistry(licenseRegistry).hasIpAttachedLicenseTerms(ipId, licenseTemplate, licenseTermsId)) return;

ILicensingModule(licensingModule).attachLicenseTerms(ipId, licenseTemplate, licenseTermsId);
try ILicensingModule(licensingModule).attachLicenseTerms(ipId, licenseTemplate, licenseTermsId) {
return; // license terms are attached successfully
} catch (bytes memory reason) {
// if the error is not that the license terms are already attached, revert with the original error
if (CoreErrors.LicenseRegistry__LicenseTermsAlreadyAttached.selector != bytes4(reason)) {
assembly {
revert(add(reason, 32), mload(reason))
}
}
}
}
}
115 changes: 115 additions & 0 deletions test/workflows/LicenseAttachmentWorkflows.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity 0.8.26;

// external
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
import { Errors as CoreErrors } from "@storyprotocol/core/lib/Errors.sol";
import { ICoreMetadataModule } from "@storyprotocol/core/interfaces/modules/metadata/ICoreMetadataModule.sol";
import { IIPAccount } from "@storyprotocol/core/interfaces/IIPAccount.sol";
import { ILicensingModule } from "@storyprotocol/core/interfaces/modules/licensing/ILicensingModule.sol";
Expand Down Expand Up @@ -158,4 +159,118 @@ contract LicenseAttachmentWorkflowsTest is BaseTest {
sigAttach: WorkflowStructs.SignatureData({ signer: u.alice, deadline: deadline, signature: sigAttach })
});
}

function test_LicenseAttachmentWorkflows_registerPILTermsAndAttach_idempotency()
public
withCollection
withIp(u.alice)
{
address payable ipId = ipAsset[1].ipId;
uint256 deadline = block.timestamp + 1000;

(bytes memory signature, , bytes memory data) = _getSetPermissionSigForPeriphery({
ipId: ipId,
to: address(licenseAttachmentWorkflows),
module: address(licensingModule),
selector: ILicensingModule.attachLicenseTerms.selector,
deadline: deadline,
state: IIPAccount(ipId).state(),
signerSk: sk.alice
});

IIPAccount(ipId).executeWithSig({
to: address(accessController),
value: 0,
data: data,
signer: u.alice,
deadline: deadline,
signature: signature
});

uint256 licenseTermsId1 = licenseAttachmentWorkflows.registerPILTermsAndAttach({
ipId: ipId,
terms: PILFlavors.commercialUse({
mintingFee: 100,
currencyToken: address(mockToken),
royaltyPolicy: address(royaltyPolicyLAP)
})
});

// attach the same license terms to the IP again, but it shouldn't revert
uint256 licenseTermsId2 = licenseAttachmentWorkflows.registerPILTermsAndAttach({
ipId: ipId,
terms: PILFlavors.commercialUse({
mintingFee: 100,
currencyToken: address(mockToken),
royaltyPolicy: address(royaltyPolicyLAP)
})
});

assertEq(licenseTermsId1, licenseTermsId2);
}

function test_revert_registerPILTermsAndAttach_DerivativesCannotAddLicenseTerms()
public
withCollection
whenCallerHasMinterRole
withEnoughTokens(address(licenseAttachmentWorkflows))
{
(address ipIdParent, , uint256 licenseTermsIdParent) = licenseAttachmentWorkflows
.mintAndRegisterIpAndAttachPILTerms({
spgNftContract: address(nftContract),
recipient: caller,
ipMetadata: ipMetadataDefault,
terms: PILFlavors.nonCommercialSocialRemixing()
});

address[] memory parentIpIds = new address[](1);
parentIpIds[0] = ipIdParent;

uint256[] memory licenseTermsIds = new uint256[](1);
licenseTermsIds[0] = licenseTermsIdParent;

(address ipIdChild, uint256 tokenIdChild) = derivativeWorkflows.mintAndRegisterIpAndMakeDerivative({
spgNftContract: address(nftContract),
derivData: WorkflowStructs.MakeDerivative({
parentIpIds: parentIpIds,
licenseTemplate: address(pilTemplate),
licenseTermsIds: licenseTermsIds,
royaltyContext: ""
}),
ipMetadata: ipMetadataDefault,
recipient: caller
});

uint256 deadline = block.timestamp + 1000;

(bytes memory signature, , bytes memory data) = _getSetPermissionSigForPeriphery({
ipId: ipIdChild,
to: address(licenseAttachmentWorkflows),
module: address(licensingModule),
selector: ILicensingModule.attachLicenseTerms.selector,
deadline: deadline,
state: IIPAccount(payable(ipIdChild)).state(),
signerSk: sk.alice
});

IIPAccount(payable(ipIdChild)).executeWithSig({
to: address(accessController),
value: 0,
data: data,
signer: u.alice,
deadline: deadline,
signature: signature
});

// attach a different license terms to the child ip, should revert with the correct error
vm.expectRevert(CoreErrors.LicensingModule__DerivativesCannotAddLicenseTerms.selector);
licenseAttachmentWorkflows.registerPILTermsAndAttach({
ipId: ipIdChild,
terms: PILFlavors.commercialUse({
mintingFee: 100,
currencyToken: address(mockToken),
royaltyPolicy: address(royaltyPolicyLAP)
})
});
}
}
Loading