From a5056293af1307b4c950e9cf015cb1fb0d2693c7 Mon Sep 17 00:00:00 2001 From: Jongwon Park Date: Mon, 8 Apr 2024 14:48:21 -0500 Subject: [PATCH] fix(test): Integrate tests with new license system (2/3) --- .../foundry/integration/BaseIntegration.t.sol | 220 +---------------- .../big-bang/SingleNftCollection.t.sol | 224 ++++++++---------- .../integration/flows/disputes/Disputes.t.sol | 96 +++++--- .../flows/licensing/LicensingScenarios.t.sol | 148 ++++++++---- .../integration/flows/royalty/Royalty.t.sol | 143 +++++------ test/foundry/utils/LicensingHelper.t.sol | 1 - 6 files changed, 348 insertions(+), 484 deletions(-) diff --git a/test/foundry/integration/BaseIntegration.t.sol b/test/foundry/integration/BaseIntegration.t.sol index 3a543be49..52e309870 100644 --- a/test/foundry/integration/BaseIntegration.t.sol +++ b/test/foundry/integration/BaseIntegration.t.sol @@ -4,13 +4,11 @@ pragma solidity 0.8.23; // external import { IERC6551Registry } from "erc6551/interfaces/IERC6551Registry.sol"; import { ERC6551AccountLib } from "erc6551/lib/ERC6551AccountLib.sol"; -import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; // contracts import { IIPAccountRegistry } from "contracts/interfaces/registries/IIPAccountRegistry.sol"; import { IIPAssetRegistry } from "contracts/interfaces/registries/IIPAssetRegistry.sol"; -import { ILicensingModule } from "contracts/interfaces/modules/licensing/ILicensingModule.sol"; // test import { MockERC721 } from "test/foundry/mocks/token/MockERC721.sol"; @@ -31,7 +29,7 @@ contract BaseIntegration is BaseTest { HELPERS //////////////////////////////////////////////////////////////////////////*/ - function registerIpAccount(address nft, uint256 tokenId, address caller) internal returns (address) { + function registerIpAccount(address nft, uint256 tokenId, address owner) internal returns (address) { address expectedAddr = ERC6551AccountLib.computeAddress( address(erc6551Registry), address(ipAccountImpl), @@ -43,8 +41,6 @@ contract BaseIntegration is BaseTest { vm.label(expectedAddr, string(abi.encodePacked("IPAccount", Strings.toString(tokenId)))); - // expect all events below when calling `ipAssetRegistry.register` - vm.expectEmit(); emit IERC6551Registry.ERC6551AccountCreated({ account: expectedAddr, @@ -75,8 +71,7 @@ contract BaseIntegration is BaseTest { registrationDate: block.timestamp }); - // policyId = 0 means no policy attached directly on creation - vm.startPrank(caller); + vm.startPrank(owner); return ipAssetRegistry.register(nft, tokenId); } @@ -84,212 +79,15 @@ contract BaseIntegration is BaseTest { return registerIpAccount(address(nft), tokenId, caller); } - function registerDerivativeIps( - uint256[] memory licenseIds, - address nft, - uint256 tokenId, - address caller, - bytes memory royaltyContext - ) internal returns (address) { - address expectedAddr = ERC6551AccountLib.computeAddress( - address(erc6551Registry), - address(ipAccountImpl), - ipAccountRegistry.IP_ACCOUNT_SALT(), - block.chainid, - nft, - tokenId - ); - - vm.label(expectedAddr, string(abi.encodePacked("IPAccount", Strings.toString(tokenId)))); - - uint256[] memory policyIds = new uint256[](licenseIds.length); - address[] memory parentIpIds = new address[](licenseIds.length); - for (uint256 i = 0; i < licenseIds.length; i++) { - policyIds[i] = licenseRegistry.policyIdForLicense(licenseIds[i]); - parentIpIds[i] = licenseRegistry.licensorIpId(licenseIds[i]); - } - - vm.expectEmit(); - emit IERC6551Registry.ERC6551AccountCreated({ - account: expectedAddr, - implementation: address(ipAccountImpl), - salt: ipAccountRegistry.IP_ACCOUNT_SALT(), - chainId: block.chainid, - tokenContract: nft, - tokenId: tokenId - }); - - vm.expectEmit(); - emit IIPAccountRegistry.IPAccountRegistered({ - account: expectedAddr, - implementation: address(ipAccountImpl), - chainId: block.chainid, - tokenContract: nft, - tokenId: tokenId - }); - - vm.expectEmit(); - emit IIPAssetRegistry.IPRegistered({ - ipId: expectedAddr, - chainId: block.chainid, - tokenContract: nft, - tokenId: tokenId, - name: string.concat(block.chainid.toString(), ": Ape #", tokenId.toString()), - uri: string.concat("https://storyprotocol.xyz/erc721/", tokenId.toString()), - registrationDate: block.timestamp - }); - - address ipId = ipAssetRegistry.register(nft, tokenId); - - _expectPolicyAddedToIpId(caller, expectedAddr, licenseIds, policyIds); - - vm.expectEmit(); - emit ILicensingModule.IpIdLinkedToParents({ caller: caller, ipId: expectedAddr, parentIpIds: parentIpIds }); - - if (licenseIds.length == 1) { - vm.expectEmit(); - emit IERC1155.TransferSingle({ - operator: address(licensingModule), - from: caller, - to: address(0), // burn addr - id: licenseIds[0], - value: 1 - }); - } else { - uint256[] memory values = new uint256[](licenseIds.length); - for (uint256 i = 0; i < licenseIds.length; ++i) { - values[i] = 1; - } - - vm.expectEmit(); - emit IERC1155.TransferBatch({ - operator: address(licensingModule), - from: caller, - to: address(0), // burn addr - ids: licenseIds, - values: values - }); - } - - vm.startPrank(caller); - licensingModule.linkIpToParents(licenseIds, ipId, royaltyContext); - return expectedAddr; - } - - function registerDerivativeIp( - uint256 licenseId, - address nft, - uint256 tokenId, - address caller, - bytes memory royaltyContext - ) internal returns (address) { - uint256[] memory licenseIds = new uint256[](1); - licenseIds[0] = licenseId; - return registerDerivativeIps(licenseIds, nft, tokenId, caller, royaltyContext); - } - - function linkIpToParents( - uint256[] memory licenseIds, + function registerDerivativeWithLicenseTokens( address ipId, - address caller, - bytes memory royaltyContext + uint256[] memory licenseTokenIds, + bytes memory royaltyContext, + address caller ) internal { - uint256[] memory policyIds = new uint256[](licenseIds.length); - address[] memory parentIpIds = new address[](licenseIds.length); - uint256[] memory prevLicenseAmounts = new uint256[](licenseIds.length); - uint256[] memory values = new uint256[](licenseIds.length); - - for (uint256 i = 0; i < licenseIds.length; i++) { - policyIds[i] = licenseRegistry.policyIdForLicense(licenseIds[i]); - parentIpIds[i] = licenseRegistry.licensorIpId(licenseIds[i]); - prevLicenseAmounts[i] = licenseRegistry.balanceOf(caller, licenseIds[i]); - values[i] = 1; - vm.expectEmit(); - emit ILicensingModule.PolicyAddedToIpId({ - caller: caller, - ipId: ipId, - policyId: policyIds[i], - index: i, - isInherited: true - }); - } - - vm.expectEmit(); - emit ILicensingModule.IpIdLinkedToParents({ caller: caller, ipId: ipId, parentIpIds: parentIpIds }); - - if (licenseIds.length == 1) { - vm.expectEmit(); - emit IERC1155.TransferSingle({ - operator: address(licensingModule), - from: caller, - to: address(0), // burn addr - id: licenseIds[0], - value: 1 - }); - } else { - vm.expectEmit(); - emit IERC1155.TransferBatch({ - operator: caller, - from: caller, - to: address(0), // burn addr - ids: licenseIds, - values: values - }); - } - vm.startPrank(caller); - licensingModule.linkIpToParents(licenseIds, ipId, royaltyContext); - - for (uint256 i = 0; i < licenseIds.length; i++) { - assertEq( - licenseRegistry.balanceOf(caller, licenseIds[i]), - prevLicenseAmounts[i] - 1, - "license not burnt on linking" - ); - assertTrue(licensingModule.isParent(parentIpIds[i], ipId), "parent IP account is not parent"); - (uint256 index, bool isInherited, ) = licensingModule.policyStatus(parentIpIds[i], policyIds[i]); - assertEq( - keccak256(abi.encode(licensingModule.policyForIpAtIndex(isInherited, parentIpIds[i], index))), - keccak256(abi.encode(licensingModule.policyForIpAtIndex(true, ipId, i))), - "policy not the same in parent to child" - ); - } - } - - function linkIpToParent(uint256 licenseId, address ipId, address caller, bytes memory royaltyContext) internal { - uint256[] memory licenseIds = new uint256[](1); - licenseIds[0] = licenseId; - linkIpToParents(licenseIds, ipId, caller, royaltyContext); - } - - function _expectPolicyAddedToIpId( - address caller, - address ipId, - uint256[] memory licenseIds, - uint256[] memory policyIds - ) internal { - uint256 policyIdIndexTracker = 0; // start from 0 since this is a new IP (derivative) - for (uint256 i = 0; i < licenseIds.length; i++) { - bool isNewlyAddedPolicy = true; - for (uint256 j = 0; j < licenseIds.length; j++) { - if (j == i) continue; - if (policyIds[j] == policyIds[i]) { - isNewlyAddedPolicy = false; - break; - } - } - - if (isNewlyAddedPolicy) { - vm.expectEmit(); - emit ILicensingModule.PolicyAddedToIpId({ - caller: caller, - ipId: ipId, - policyId: policyIds[i], - index: policyIdIndexTracker, - isInherited: true - }); - policyIdIndexTracker++; - } - } + // TODO: events check + licensingModule.registerDerivativeWithLicenseTokens(ipId, licenseTokenIds, royaltyContext); + vm.stopPrank(); } } diff --git a/test/foundry/integration/big-bang/SingleNftCollection.t.sol b/test/foundry/integration/big-bang/SingleNftCollection.t.sol index eca6a5892..db5b4a608 100644 --- a/test/foundry/integration/big-bang/SingleNftCollection.t.sol +++ b/test/foundry/integration/big-bang/SingleNftCollection.t.sol @@ -7,7 +7,7 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS // contract import { IIPAccount } from "../../../../contracts/interfaces/IIPAccount.sol"; import { Errors } from "../../../../contracts/lib/Errors.sol"; -import { PILPolicy } from "../../../../contracts/modules/licensing/PILPolicyFrameworkManager.sol"; +import { PILTerms } from "../../../../contracts/interfaces/modules/licensing/IPILicenseTemplate.sol"; // test import { BaseIntegration } from "../BaseIntegration.t.sol"; @@ -17,9 +17,9 @@ import { MockERC721 } from "../../mocks/token/MockERC721.sol"; contract BigBang_Integration_SingleNftCollection is BaseIntegration { using EnumerableSet for EnumerableSet.UintSet; - MockTokenGatedHook internal mockTokenGatedHook; + MockTokenGatedHook internal mockTokenGatedHook = new MockTokenGatedHook(); - MockERC721 internal mockGatedNft; + MockERC721 internal mockGatedNft = new MockERC721("MockGatedNft"); mapping(uint256 tokenId => address ipAccount) internal ipAcct; @@ -29,57 +29,35 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { uint256 internal constant mintingFee = 100 ether; - function setUp() public override { - super.setUp(); + uint256 internal ncSocialRemixTermsId; - mockTokenGatedHook = new MockTokenGatedHook(); - mockGatedNft = new MockERC721("MockGatedNft"); + uint256 internal commDerivTermsId; - // Add PIL PFM policies + function setUp() public override { + super.setUp(); - _setPILPolicyFrameworkManager(); + ncSocialRemixTermsId = registerSelectedPILicenseTerms_NonCommercialSocialRemixing(); - _addPILPolicyWihtMintPayment( - "com_deriv_cheap_flexible", // ==> policyIds["pil_com_deriv_cheap_flexible"] - true, - address(royaltyPolicyLAP), - mintingFee, - address(mockToken), - PILPolicy({ - attribution: false, + commDerivTermsId = registerSelectedPILicenseTerms( + "commercial_flexible", + PILTerms({ + transferable: true, + royaltyPolicy: address(royaltyPolicyLAP), + mintingFee: mintingFee, + expiration: 0, commercialUse: true, - commercialAttribution: true, + commercialAttribution: false, commercializerChecker: address(mockTokenGatedHook), + // Gated via balance > 1 of mockGatedNft commercializerCheckerData: abi.encode(address(mockGatedNft)), commercialRevShare: derivCheapFlexibleRevShare, + commercialRevCelling: 0, derivativesAllowed: true, - derivativesAttribution: true, + derivativesAttribution: false, derivativesApproval: false, derivativesReciprocal: false, - territories: new string[](0), - distributionChannels: new string[](0), - contentRestrictions: new string[](0) - }) - ); - - _addPILPolicy( - "noncom_deriv_reciprocal_derivative", // ==> policyIds["pil_noncom_deriv_reciprocal_derivative"] - false, - address(0), - PILPolicy({ - attribution: false, - commercialUse: false, - commercialAttribution: false, - commercializerChecker: address(0), - commercializerCheckerData: "", - commercialRevShare: 0, - derivativesAllowed: true, - derivativesAttribution: true, - derivativesApproval: false, - derivativesReciprocal: true, - territories: new string[](0), - distributionChannels: new string[](0), - contentRestrictions: new string[](0) + derivativeRevCelling: 0, + currency: address(erc20) }) ); } @@ -113,23 +91,24 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { ///////////////////////////////////////////////////////////////*/ vm.startPrank(u.alice); - licensingModule.addPolicyToIp(ipAcct[1], policyIds["pil_com_deriv_cheap_flexible"]); - licensingModule.addPolicyToIp(ipAcct[100], policyIds["pil_noncom_deriv_reciprocal_derivative"]); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), commDerivTermsId); + licensingModule.attachLicenseTerms(ipAcct[100], address(pilTemplate), ncSocialRemixTermsId); vm.startPrank(u.bob); - licensingModule.addPolicyToIp(ipAcct[3], policyIds["pil_com_deriv_cheap_flexible"]); - licensingModule.addPolicyToIp(ipAcct[300], policyIds["pil_com_deriv_cheap_flexible"]); + licensingModule.attachLicenseTerms(ipAcct[3], address(pilTemplate), commDerivTermsId); + licensingModule.attachLicenseTerms(ipAcct[300], address(pilTemplate), commDerivTermsId); vm.startPrank(u.bob); // NOTE: the two calls below achieve the same functionality - // licensingModule.addPolicyToIp(ipAcct[3], policyIds["pil_noncom_deriv_reciprocal_derivative"]); + // licensingModule.attachLicenseTerms(ipAcct[3], address(pilTemplate), ncSocialRemixTermsId); IIPAccount(payable(ipAcct[3])).execute( address(licensingModule), 0, abi.encodeWithSignature( - "addPolicyToIp(address,uint256)", + "attachLicenseTerms(address,address,uint256)", ipAcct[3], - policyIds["pil_noncom_deriv_reciprocal_derivative"] + address(pilTemplate), + ncSocialRemixTermsId ) ); @@ -151,17 +130,17 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { mockToken.approve(address(royaltyPolicyLAP), mintingFee); uint256[] memory carl_license_from_root_alice = new uint256[](1); - carl_license_from_root_alice[0] = licensingModule.mintLicense( - policyIds["pil_com_deriv_cheap_flexible"], - ipAcct[1], - 1, - u.carl, - "" - ); + carl_license_from_root_alice[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commDerivTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); ipAcct[6] = registerIpAccount(mockNFT, 6, u.carl); - - linkIpToParents(carl_license_from_root_alice, ipAcct[6], u.carl, ""); + registerDerivativeWithLicenseTokens(ipAcct[6], carl_license_from_root_alice, "", u.carl); } // Carl mints 2 license for policy "pil_noncom_deriv_reciprocal_derivative" on Bob's NFT 3 IPAccount @@ -169,23 +148,24 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { // Carl activates one of the two licenses on his NFT 7 IPAccount, linking as child to Bob's NFT 3 IPAccount { vm.startPrank(u.carl); - mockNFT.mintId(u.carl, 7); // NFT for Carl's IPAccount7 + uint256 tokenId = 7; + mockNFT.mintId(u.carl, tokenId); // NFT for Carl's IPAccount7 // Carl is minting license on non-commercial policy, so no commercializer checker is involved. // Thus, no need to mint anything (although Carl already has mockGatedNft from above) uint256[] memory carl_license_from_root_bob = new uint256[](1); - carl_license_from_root_bob[0] = licensingModule.mintLicense( - policyIds["pil_noncom_deriv_reciprocal_derivative"], - ipAcct[3], - 1, - u.carl, - "" - ); - - // TODO: events check - address ipId = ipAssetRegistry.register(address(mockNFT), 7); - licensingModule.linkIpToParents(carl_license_from_root_bob, ipId, ""); + carl_license_from_root_bob[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[3], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + + ipAcct[tokenId] = registerIpAccount(address(mockNFT), tokenId, u.carl); + registerDerivativeWithLicenseTokens(ipAcct[tokenId], carl_license_from_root_bob, "", u.carl); } // Alice mints 2 license for policy "pil_com_deriv_cheap_flexible" on Bob's NFT 3 IPAccount @@ -204,27 +184,25 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { mockGatedNft.mint(u.alice); uint256[] memory alice_license_from_root_bob = new uint256[](1); - alice_license_from_root_bob[0] = licensingModule.mintLicense( - policyIds["pil_com_deriv_cheap_flexible"], - ipAcct[3], - mintAmount, - u.alice, - "" - ); + alice_license_from_root_bob[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[3], + licenseTemplate: address(pilTemplate), + licenseTermsId: commDerivTermsId, + amount: 2, + receiver: u.alice, + royaltyContext: "" + }); // ID 0 (first license) ipAcct[2] = registerIpAccount(mockNFT, 2, u.alice); - linkIpToParents(alice_license_from_root_bob, ipAcct[2], u.alice, ""); + registerDerivativeWithLicenseTokens(ipAcct[2], alice_license_from_root_bob, "", u.alice); uint256 tokenId = 99999999; mockNFT.mintId(u.alice, tokenId); - ipAcct[tokenId] = registerDerivativeIps( - alice_license_from_root_bob, - address(mockNFT), - tokenId, - u.alice, // caller - "" - ); + alice_license_from_root_bob[0] = alice_license_from_root_bob[0] + 1; // ID 1 (second license) + + ipAcct[tokenId] = registerIpAccount(address(mockNFT), tokenId, u.alice); + registerDerivativeWithLicenseTokens(ipAcct[tokenId], alice_license_from_root_bob, "", u.alice); } // Carl mints licenses and linkts to multiple parents @@ -242,40 +220,50 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { uint256[] memory carl_licenses = new uint256[](2); // Commercial license (Carl already has mockGatedNft from above, so he passes commercializer checker check) - carl_licenses[0] = licensingModule.mintLicense( - policyIds["pil_com_deriv_cheap_flexible"], // ipAcct[1] has this policy attached - ipAcct[1], - license0_mintAmount, - u.carl, - "" - ); - - // Non-commercial license - carl_licenses[1] = licensingModule.mintLicense( - policyIds["pil_noncom_deriv_reciprocal_derivative"], // ipAcct[3] has this policy attached - ipAcct[3], - 1, - u.carl, - "" - ); - - address ipId = ipAssetRegistry.register(address(mockNFT), tokenId); + carl_licenses[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commDerivTermsId, + amount: license0_mintAmount, + receiver: u.carl, + royaltyContext: "" + }); + + // NC Social Remix license + carl_licenses[1] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[3], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, // ipAcct[3] has this policy attached + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + + ipAcct[tokenId] = registerIpAccount(address(mockNFT), tokenId, u.carl); // This should revert since license[0] is commercial but license[1] is non-commercial - vm.expectRevert(Errors.LicensingModule__IncompatibleLicensorCommercialPolicy.selector); - licensingModule.linkIpToParents(carl_licenses, ipId, ""); + vm.expectRevert( + abi.encodeWithSelector( + Errors.LicensingModule__LicenseTokenNotCompatibleForDerivative.selector, + ipAcct[tokenId], + carl_licenses + ) + ); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[tokenId], carl_licenses, ""); uint256 license1_mintAmount = 500; mockToken.mint(u.carl, mintingFee * license1_mintAmount); mockToken.approve(address(royaltyPolicyLAP), mintingFee * license1_mintAmount); // Modify license[1] to a Commercial license - carl_licenses[1] = licensingModule.mintLicense( - policyIds["pil_com_deriv_cheap_flexible"], // ipAcct[300] has this policy attached - ipAcct[300], - license1_mintAmount, - u.carl, - "" - ); + carl_licenses[1] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[300], + licenseTemplate: address(pilTemplate), + licenseTermsId: commDerivTermsId, + amount: license1_mintAmount, + receiver: u.carl, + royaltyContext: "" + }); + carl_licenses[1] = carl_licenses[1] + license1_mintAmount - 1; // use last license ID minted from above // Linking 2 licenses, ID 1 and ID 4. // These licenses are from 2 different parents, ipAcct[1] and ipAcct[300], respectively. @@ -283,13 +271,9 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration { // This should succeed since both license[0] and license[1] are commercial tokenId = 70001; mockNFT.mintId(u.carl, tokenId); - registerDerivativeIps( - carl_licenses, // ipAcct[1] and ipAcct[3] licenses - address(mockNFT), - tokenId, - u.carl, // caller - "" - ); + + ipAcct[tokenId] = registerIpAccount(address(mockNFT), tokenId, u.carl); + registerDerivativeWithLicenseTokens(ipAcct[tokenId], carl_licenses, "", u.carl); } } } diff --git a/test/foundry/integration/flows/disputes/Disputes.t.sol b/test/foundry/integration/flows/disputes/Disputes.t.sol index eff1fcbd0..b472839b9 100644 --- a/test/foundry/integration/flows/disputes/Disputes.t.sol +++ b/test/foundry/integration/flows/disputes/Disputes.t.sol @@ -7,33 +7,22 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // contract -import { Errors } from "contracts/lib/Errors.sol"; +import { Errors } from "../../../../../contracts/lib/Errors.sol"; // test -import { BaseIntegration } from "test/foundry/integration/BaseIntegration.t.sol"; +import { BaseIntegration } from "../../BaseIntegration.t.sol"; contract Flows_Integration_Disputes is BaseIntegration { using EnumerableSet for EnumerableSet.UintSet; using Strings for *; mapping(uint256 tokenId => address ipAccount) internal ipAcct; - uint256 internal policyId; + uint256 internal ncSocialRemixTermsId; function setUp() public override { super.setUp(); - // Register PIL Framework - _setPILPolicyFrameworkManager(); - - // Register a License - _mapPILPolicySimple({ - name: "non-commercial-remix", - commercial: false, - derivatives: true, - reciprocal: true, - commercialRevShare: 0 - }); - policyId = _registerPILPolicyFromMapping("non-commercial-remix"); + ncSocialRemixTermsId = registerSelectedPILicenseTerms_NonCommercialSocialRemixing(); // Register an original work with both policies set mockNFT.mintId(u.alice, 1); @@ -45,28 +34,51 @@ contract Flows_Integration_Disputes is BaseIntegration { ipAcct[3] = registerIpAccount(mockNFT, 3, u.carl); vm.startPrank(u.alice); - licensingModule.addPolicyToIp(ipAcct[1], _getPilPolicyId("non-commercial-remix")); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), ncSocialRemixTermsId); vm.stopPrank(); } function test_Integration_Disputes_revert_cannotMintFromDisputedIp() public { - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 0); + assertEq(licenseToken.balanceOf(u.carl), 0); + vm.prank(u.carl); - licensingModule.mintLicense(policyId, ipAcct[1], 1, u.carl, ""); - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 1); + licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + assertEq(licenseToken.balanceOf(u.carl), 1); _disputeIp(u.bob, ipAcct[1]); vm.prank(u.carl); vm.expectRevert(Errors.LicensingModule__DisputedIpId.selector); - licensingModule.mintLicense(policyId, ipAcct[1], 1, u.carl, ""); + licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); } - function test_Integration_Disputes_revert_cannotLinkDisputedIp() public { - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 0); + function test_Integration_Disputes_revert_cannotRegisterDerivativeFromDisputedIpParent() public { + assertEq(licenseToken.balanceOf(u.carl), 0); + vm.prank(u.carl); - uint256 licenseId = licensingModule.mintLicense(policyId, ipAcct[1], 1, u.carl, ""); - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 1); + uint256 licenseId = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + assertEq(licenseToken.balanceOf(u.carl), 1); _disputeIp(u.bob, ipAcct[1]); @@ -74,22 +86,30 @@ contract Flows_Integration_Disputes is BaseIntegration { licenseIds[0] = licenseId; vm.prank(u.carl); - vm.expectRevert(Errors.LicensingModule__LinkingRevokedLicense.selector); - licensingModule.linkIpToParents(licenseIds, ipAcct[3], ""); + vm.expectRevert(abi.encodeWithSelector(Errors.LicenseToken__RevokedLicense.selector, licenseId)); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[3], licenseIds, ""); } function test_Integration_Disputes_transferLicenseAfterIpDispute() public { - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 0); + assertEq(licenseToken.balanceOf(u.carl), 0); + vm.prank(u.carl); - uint256 licenseId = licensingModule.mintLicense(policyId, ipAcct[1], 1, u.carl, ""); - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 1); + uint256 licenseId = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + assertEq(licenseToken.balanceOf(u.carl), 1); _disputeIp(u.bob, ipAcct[1]); // If the IP asset is disputed, license owners won't be able to transfer license NFTs vm.prank(u.carl); - vm.expectRevert(Errors.LicenseRegistry__RevokedLicense.selector); - licenseRegistry.safeTransferFrom(u.carl, u.bob, licenseId, 1, ""); + vm.expectRevert(abi.encodeWithSelector(Errors.LicenseToken__RevokedLicense.selector, licenseId)); + licenseToken.transferFrom(u.carl, u.bob, licenseId); } function test_Integration_Disputes_mintLicenseAfterDisputeIsResolved() public { @@ -98,10 +118,18 @@ contract Flows_Integration_Disputes is BaseIntegration { vm.prank(u.bob); disputeModule.resolveDispute(disputeId); - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 0); + assertEq(licenseToken.balanceOf(u.carl), 0); + vm.prank(u.carl); - licensingModule.mintLicense(policyId, ipAcct[1], 1, u.carl, ""); - assertEq(licenseRegistry.balanceOf(u.carl, policyId), 1); + licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.carl, + royaltyContext: "" + }); + assertEq(licenseToken.balanceOf(u.carl), 1); } function _disputeIp(address disputeInitiator, address ipAddrToDispute) internal returns (uint256 disputeId) { diff --git a/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol b/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol index c0c38e12b..24340e351 100644 --- a/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol +++ b/test/foundry/integration/flows/licensing/LicensingScenarios.t.sol @@ -7,103 +7,155 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; // contract -import { PILFlavors } from "contracts/lib/PILFlavors.sol"; +import { PILFlavors } from "../../../../../contracts/lib/PILFlavors.sol"; // test -import { BaseIntegration } from "test/foundry/integration/BaseIntegration.t.sol"; +import { BaseIntegration } from "../..//BaseIntegration.t.sol"; contract Licensing_Scenarios is BaseIntegration { using EnumerableSet for EnumerableSet.UintSet; using Strings for *; mapping(uint256 tokenId => address ipAccount) internal ipAcct; - uint256 internal nonCommRemixPoliciyId; function setUp() public override { super.setUp(); - // Register PIL Framework - _setPILicenseTemplate(); - // Register an original work with both policies set mockNFT.mintId(u.alice, 1); mockNFT.mintId(u.bob, 2); ipAcct[1] = registerIpAccount(mockNFT, 1, u.alice); ipAcct[2] = registerIpAccount(mockNFT, 2, u.bob); - - nonCommRemixPoliciyId = _pilFramework().registerPolicy(PILFlavors.nonCommercialSocialRemixing()); } - function test_flavors_getId() public { - uint256 id = PILFlavors.getNonCommercialSocialRemixingId(licensingModule, address(_pilFramework())); - assertEq(id, nonCommRemixPoliciyId); + function test_Integration_LicensingScenarios_PILFlavors_getId() public { + uint256 ncSocialRemixTermsId = registerSelectedPILicenseTerms_NonCommercialSocialRemixing(); + assertEq(ncSocialRemixTermsId, PILFlavors.getNonCommercialSocialRemixingId(pilTemplate)); + uint32 commercialRevShare = 10; - uint256 commRemixPolicyId = _pilFramework().registerPolicy( - PILFlavors.commercialRemix(commercialRevShare, address(royaltyPolicyLAP)) + uint256 mintingFee = 100; + + uint256 commRemixTermsId = registerSelectedPILicenseTerms( + "commercial_remix", + PILFlavors.commercialRemix({ + commercialRevShare: commercialRevShare, + mintingFee: mintingFee, + royaltyPolicy: address(royaltyPolicyLAP), + currencyToken: address(USDC) + }) ); assertEq( - commRemixPolicyId, - PILFlavors.getcommercialRemixId( - licensingModule, - address(_pilFramework()), - commercialRevShare, - address(royaltyPolicyLAP) - ) + commRemixTermsId, + PILFlavors.getCommercialRemixId({ + pilTemplate: pilTemplate, + commercialRevShare: commercialRevShare, + mintingFee: mintingFee, + currencyToken: address(USDC), + royaltyPolicy: address(royaltyPolicyLAP) + }) ); - uint256 mintFee = 100; - uint256 commPolicyId = _pilFramework().registerPolicy( - PILFlavors.commercialUse(mintFee, address(USDC), address(royaltyPolicyLAP)) + uint256 commTermsId = registerSelectedPILicenseTerms( + "commercial_use", + PILFlavors.commercialUse({ + mintingFee: mintingFee, + currencyToken: address(USDC), + royaltyPolicy: address(royaltyPolicyLAP) + }) ); assertEq( - commPolicyId, - PILFlavors.getCommercialUseId( - licensingModule, - address(_pilFramework()), - mintFee, - address(USDC), - address(royaltyPolicyLAP) - ) + commTermsId, + PILFlavors.getCommercialUseId({ + pilTemplate: pilTemplate, + mintingFee: mintingFee, + currencyToken: address(USDC), + royaltyPolicy: address(royaltyPolicyLAP) + }) ); } - function test_ipaHasNonCommercialAndCommercialPolicy_mintingLicenseFromCommercial() public { - // Register commercial remixing policy + // solhint-disable-next-line max-line-length + function test_Integration_LicensingScenarios_ipaHasNonCommercialAndCommercialPolicy_mintingLicenseFromCommercial() + public + { uint32 commercialRevShare = 10; - uint256 commRemixPolicyId = _pilFramework().registerPolicy( - PILFlavors.commercialRemix(commercialRevShare, address(royaltyPolicyLAP)) + uint256 mintingFee = 100; + + // Register non-commercial social remixing policy + uint256 ncSocialRemixTermsId = registerSelectedPILicenseTerms_NonCommercialSocialRemixing(); + + // Register commercial remixing policy + uint256 commRemixTermsId = registerSelectedPILicenseTerms( + "commercial_remix", + PILFlavors.commercialRemix({ + commercialRevShare: commercialRevShare, + mintingFee: mintingFee, + royaltyPolicy: address(royaltyPolicyLAP), + currencyToken: address(USDC) + }) ); // Register commercial use policy - uint256 mintFee = 100; - uint256 commPolicyId = _pilFramework().registerPolicy( - PILFlavors.commercialUse(mintFee, address(USDC), address(royaltyPolicyLAP)) + uint256 commTermsId = registerSelectedPILicenseTerms( + "commercial_use", + PILFlavors.commercialUse({ + mintingFee: mintingFee, + currencyToken: address(USDC), + royaltyPolicy: address(royaltyPolicyLAP) + }) ); + uint256[] memory licenseIds = new uint256[](1); // Add policies to IP account vm.startPrank(u.alice); - licensingModule.addPolicyToIp(ipAcct[1], commRemixPolicyId); - licensingModule.addPolicyToIp(ipAcct[1], nonCommRemixPoliciyId); - licensingModule.addPolicyToIp(ipAcct[1], commPolicyId); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), commRemixTermsId); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), ncSocialRemixTermsId); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), commTermsId); vm.stopPrank(); + // Register new IPAs mockNFT.mintId(u.bob, 3); ipAcct[3] = registerIpAccount(mockNFT, 3, u.bob); mockNFT.mintId(u.bob, 4); ipAcct[4] = registerIpAccount(mockNFT, 4, u.bob); + // Mint license for Non-commercial remixing, then link to new IPA to make it a derivative vm.startPrank(u.bob); - licenseIds[0] = licensingModule.mintLicense(nonCommRemixPoliciyId, ipAcct[1], 1, u.bob, ""); - licensingModule.linkIpToParents(licenseIds, ipAcct[2], ""); + licenseIds[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: ncSocialRemixTermsId, + amount: 1, + receiver: u.bob, + royaltyContext: "" + }); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[2], licenseIds, ""); + // Mint license for commercial use, then link to new IPA to make it a derivative - IERC20(USDC).approve(address(royaltyPolicyLAP), mintFee); - licenseIds[0] = licensingModule.mintLicense(commPolicyId, ipAcct[1], 1, u.bob, ""); - licensingModule.linkIpToParents(licenseIds, ipAcct[3], ""); + IERC20(USDC).approve(address(royaltyPolicyLAP), mintingFee); + licenseIds[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commTermsId, + amount: 1, + receiver: u.bob, + royaltyContext: "" + }); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[3], licenseIds, ""); + // Mint license for commercial remixing, then link to new IPA to make it a derivative - licenseIds[0] = licensingModule.mintLicense(commRemixPolicyId, ipAcct[1], 1, u.bob, ""); - licensingModule.linkIpToParents(licenseIds, ipAcct[4], ""); + IERC20(USDC).approve(address(royaltyPolicyLAP), mintingFee); + licenseIds[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commRemixTermsId, + amount: 1, + receiver: u.bob, + royaltyContext: "" + }); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[4], licenseIds, ""); vm.stopPrank(); } diff --git a/test/foundry/integration/flows/royalty/Royalty.t.sol b/test/foundry/integration/flows/royalty/Royalty.t.sol index 7b18fe7ba..7f677ce23 100644 --- a/test/foundry/integration/flows/royalty/Royalty.t.sol +++ b/test/foundry/integration/flows/royalty/Royalty.t.sol @@ -5,12 +5,16 @@ pragma solidity 0.8.23; import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ERC20, IERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { IRoyaltyModule } from "contracts/interfaces/modules/royalty/IRoyaltyModule.sol"; -import { IpRoyaltyVault } from "contracts/modules/royalty/policies/IpRoyaltyVault.sol"; -import { IIpRoyaltyVault } from "contracts/interfaces/modules/royalty/policies/IIpRoyaltyVault.sol"; + +// contracts +import { IRoyaltyModule } from "../../../../../contracts/interfaces/modules/royalty/IRoyaltyModule.sol"; +import { IpRoyaltyVault } from "../../../../../contracts/modules/royalty/policies/IpRoyaltyVault.sol"; +import { IIpRoyaltyVault } from "../../../../../contracts/interfaces/modules/royalty/policies/IIpRoyaltyVault.sol"; +import { Errors } from "../../../../../contracts/lib/Errors.sol"; +import { PILFlavors } from "../../../../../contracts/lib/PILFlavors.sol"; // test -import { BaseIntegration } from "test/foundry/integration/BaseIntegration.t.sol"; +import { BaseIntegration } from "../../BaseIntegration.t.sol"; contract Flows_Integration_Disputes is BaseIntegration { using EnumerableSet for EnumerableSet.UintSet; @@ -18,31 +22,22 @@ contract Flows_Integration_Disputes is BaseIntegration { mapping(uint256 tokenId => address ipAccount) internal ipAcct; - address internal royaltyPolicyAddr; // must be assigned AFTER super.setUp() - address internal mintingFeeToken; // must be assigned AFTER super.setUp() uint32 internal defaultCommRevShare = 10 * 10 ** 6; // 10% uint256 internal mintingFee = 7 ether; + uint256 internal commRemixTermsId; function setUp() public override { super.setUp(); - // Register PIL Framework - _setPILPolicyFrameworkManager(); - - royaltyPolicyAddr = address(royaltyPolicyLAP); - mintingFeeToken = address(erc20); - - // Register a License - _mapPILPolicyCommercial({ - name: "commercial-remix", - derivatives: true, - reciprocal: true, - commercialRevShare: defaultCommRevShare, - royaltyPolicy: royaltyPolicyAddr, - mintingFeeToken: mintingFeeToken, - mintingFee: mintingFee - }); - _registerPILPolicyFromMapping("commercial-remix"); + commRemixTermsId = registerSelectedPILicenseTerms( + "commercial_remix", + PILFlavors.commercialRemix({ + mintingFee: mintingFee, + commercialRevShare: defaultCommRevShare, + royaltyPolicy: address(royaltyPolicyLAP), + currencyToken: address(erc20) + }) + ); // Register an original work with both policies set mockNFT.mintId(u.alice, 1); @@ -54,11 +49,10 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.alice); - ipAcct[1] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 1); + ipAcct[1] = registerIpAccount(mockNFT, 1, u.alice); vm.label(ipAcct[1], "IPAccount1"); - registerIpAccount(mockNFT, 1, u.alice); - licensingModule.addPolicyToIp(ipAcct[1], _getPilPolicyId("commercial-remix")); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), commRemixTermsId); vm.stopPrank(); } @@ -67,28 +61,36 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.bob); - ipAcct[2] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 2); - vm.label(ipAcct[2], "IPAccount2"); - uint256 mintAmount = 3; - erc20.approve(address(royaltyPolicyAddr), mintAmount * mintingFee); + erc20.approve(address(royaltyPolicyLAP), mintAmount * mintingFee); - uint256[] memory licenseIds = new uint256[](1); + uint256[] memory licenseIds = new uint256[](3); vm.expectEmit(address(royaltyModule)); emit IRoyaltyModule.LicenseMintingFeePaid(ipAcct[1], u.bob, address(erc20), mintAmount * mintingFee); - licenseIds[0] = licensingModule.mintLicense( - _getPilPolicyId("commercial-remix"), - ipAcct[1], - mintAmount, - u.bob, - "" - ); - - address ipId = ipAssetRegistry.register(address(mockNFT), 2); - if (licenseIds.length != 0) { - licensingModule.linkIpToParents(licenseIds, ipId, ""); - } + + licenseIds[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commRemixTermsId, + amount: mintAmount, + receiver: u.bob, + royaltyContext: "" + }); // first license minted + licenseIds[1] = licenseIds[0] + 1; // second license minted + licenseIds[2] = licenseIds[0] + 2; // third license minted + + ipAcct[2] = registerIpAccount(address(mockNFT), 2, u.bob); + + vm.expectRevert(Errors.RoyaltyPolicyLAP__AboveParentLimit.selector); + licensingModule.registerDerivativeWithLicenseTokens(ipAcct[2], licenseIds, ""); + + // can link max two + uint256[] memory licenseIdsMax = new uint256[](1); + licenseIdsMax[0] = licenseIds[0]; + + registerDerivativeWithLicenseTokens(ipAcct[2], licenseIdsMax, "", u.bob); + vm.stopPrank(); } @@ -98,38 +100,35 @@ contract Flows_Integration_Disputes is BaseIntegration { { vm.startPrank(u.carl); - ipAcct[3] = ipAccountRegistry.ipAccount(block.chainid, address(mockNFT), 3); - vm.label(ipAcct[3], "IPAccount3"); - uint256 mintAmount = 1; uint256[] memory licenseIds = new uint256[](2); - erc20.approve(address(royaltyPolicyAddr), 2 * mintAmount * mintingFee); + erc20.approve(address(royaltyPolicyLAP), 2 * mintAmount * mintingFee); vm.expectEmit(address(royaltyModule)); emit IRoyaltyModule.LicenseMintingFeePaid(ipAcct[1], u.carl, address(erc20), mintAmount * mintingFee); - licenseIds[0] = licensingModule.mintLicense( - _getPilPolicyId("commercial-remix"), - ipAcct[1], // grandparent, root IP - 1, - u.carl, - "" - ); + licenseIds[0] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[1], + licenseTemplate: address(pilTemplate), + licenseTermsId: commRemixTermsId, + amount: mintAmount, + receiver: u.carl, + royaltyContext: "" + }); vm.expectEmit(address(royaltyModule)); emit IRoyaltyModule.LicenseMintingFeePaid(ipAcct[2], u.carl, address(erc20), mintAmount * mintingFee); - licenseIds[1] = licensingModule.mintLicense( - _getPilPolicyId("commercial-remix"), - ipAcct[2], // parent, is child IP of ipAcct[1] - 1, - u.carl, - "" - ); - - address ipId = ipAssetRegistry.register(address(mockNFT), 3); - if (licenseIds.length != 0) { - licensingModule.linkIpToParents(licenseIds, ipId, ""); - } + licenseIds[1] = licensingModule.mintLicenseTokens({ + licensorIpId: ipAcct[2], // parent, is child IP of ipAcct[1] + licenseTemplate: address(pilTemplate), + licenseTermsId: commRemixTermsId, + amount: mintAmount, + receiver: u.carl, + royaltyContext: "" + }); + + ipAcct[3] = registerIpAccount(address(mockNFT), 3, u.carl); + registerDerivativeWithLicenseTokens(ipAcct[3], licenseIds, "", u.carl); vm.stopPrank(); } @@ -165,8 +164,10 @@ contract Flows_Integration_Disputes is BaseIntegration { vm.warp(block.timestamp + 7 days + 1); IpRoyaltyVault(ipRoyaltyVault).snapshot(); + // Expect 10% (10_000_000) because ipAcct[2] has only one parent (IPAccount1), with 10% absolute royalty. + vm.expectEmit(ipRoyaltyVault); - emit IERC20.Transfer({ from: ipRoyaltyVault, to: ipAcct[2], value: 10_000_000 }); // 10% + emit IERC20.Transfer({ from: ipRoyaltyVault, to: ipAcct[2], value: 10_000_000 }); vm.expectEmit(ipRoyaltyVault); emit IIpRoyaltyVault.RoyaltyTokensCollected(ipAcct[2], 10_000_000); @@ -188,15 +189,17 @@ contract Flows_Integration_Disputes is BaseIntegration { IpRoyaltyVault(ipRoyaltyVault2).snapshot(); IpRoyaltyVault(ipRoyaltyVault3).snapshot(); + // IPAccount1 should expect 10% absolute royalty from its children (IPAccount2) + // and 20% from its grandchild (IPAccount3) and so on. + vm.expectEmit(ipRoyaltyVault2); - emit IERC20.Transfer({ from: ipRoyaltyVault2, to: ipAcct[1], value: 10_000_000 }); // 10% + emit IERC20.Transfer({ from: ipRoyaltyVault2, to: ipAcct[1], value: 10_000_000 }); vm.expectEmit(ipRoyaltyVault2); emit IIpRoyaltyVault.RoyaltyTokensCollected(ipAcct[1], 10_000_000); IpRoyaltyVault(ipRoyaltyVault2).collectRoyaltyTokens(ipAcct[1]); vm.expectEmit(ipRoyaltyVault3); - // reason for 20%: absolute stack, so 10% from IPAccount2 and 10% from IPAccount3 - emit IERC20.Transfer({ from: ipRoyaltyVault3, to: ipAcct[1], value: 20_000_000 }); // 20% + emit IERC20.Transfer({ from: ipRoyaltyVault3, to: ipAcct[1], value: 20_000_000 }); vm.expectEmit(ipRoyaltyVault3); emit IIpRoyaltyVault.RoyaltyTokensCollected(ipAcct[1], 20_000_000); IpRoyaltyVault(ipRoyaltyVault3).collectRoyaltyTokens(ipAcct[1]); diff --git a/test/foundry/utils/LicensingHelper.t.sol b/test/foundry/utils/LicensingHelper.t.sol index 90c2b3f37..ba2e2abc3 100644 --- a/test/foundry/utils/LicensingHelper.t.sol +++ b/test/foundry/utils/LicensingHelper.t.sol @@ -31,7 +31,6 @@ contract LicensingHelper { PILTerms memory selectedPILicenseTerms_ ) public returns (uint256 pilSelectedLicenseTermsId) { string memory _selectionName = string(abi.encodePacked("PIL_", selectionName)); - pilSelectedLicenseTermsId = pilTemplate.registerLicenseTerms(selectedPILicenseTerms_); // pilSelectedLicenseTermsId = pilTemplate.getLicenseTermsId(selectedPILicenseTerms_);