From 5f5f3e1629eb32386d8492c68ef441b209789d65 Mon Sep 17 00:00:00 2001 From: Kingter <83567446+kingster-will@users.noreply.github.com> Date: Mon, 2 Dec 2024 22:56:43 -0800 Subject: [PATCH 1/2] Prevent Duplicate Parent IPs When Registering Derivative IP (#328) --- contracts/lib/Errors.sol | 6 +++--- contracts/registries/LicenseRegistry.sol | 8 ++++---- .../integration/flows/royalty/Royalty.t.sol | 7 +------ test/foundry/registries/LicenseRegistry.t.sol | 18 ++++++++++-------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index 9eda78d6..a62dd5aa 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -249,9 +249,6 @@ library Errors { /// @notice Provided license template does not match the IP's current license template. error LicenseRegistry__UnmatchedLicenseTemplate(address ipId, address licenseTemplate, address newLicenseTemplate); - /// @notice Provided license template and terms ID is a duplicate. - error LicenseRegistry__DuplicateLicense(address ipId, address licenseTemplate, uint256 licenseTermsId); - /// @notice Zero address provided for License Template. error LicenseRegistry__ZeroLicenseTemplate(); @@ -283,6 +280,9 @@ library Errors { /// @notice The IP has no attached the same license terms of Group IPA. error LicenseRegistry__IpHasNoGroupLicenseTerms(address groupId, address licenseTemplate, uint256 licenseTermsId); + /// @notice The IP has already linked to the same parent IP. + error LicenseRegistry__DuplicateParentIp(address ipId, address parentIpId); + /// @notice When Set LicenseConfig the license template cannot be Zero address if royalty percentage is not Zero. error LicensingModule__LicenseTemplateCannotBeZeroAddressToOverrideRoyaltyPercent(); diff --git a/contracts/registries/LicenseRegistry.sol b/contracts/registries/LicenseRegistry.sol index 22129965..0ef31b6c 100644 --- a/contracts/registries/LicenseRegistry.sol +++ b/contracts/registries/LicenseRegistry.sol @@ -249,12 +249,12 @@ contract LicenseRegistry is ILicenseRegistry, AccessManagedUpgradeable, UUPSUpgr isUsingLicenseToken ); $.childIps[parentIpIds[i]].add(childIpId); - // determine if duplicate license terms + // determine if duplicate parent IP bool isNewParent = $.parentIps[childIpId].add(parentIpIds[i]); - bool isNewTerms = $.attachedLicenseTerms[childIpId].add(licenseTermsIds[i]); - if (!isNewParent && !isNewTerms) { - revert Errors.LicenseRegistry__DuplicateLicense(parentIpIds[i], licenseTemplate, licenseTermsIds[i]); + if (!isNewParent) { + revert Errors.LicenseRegistry__DuplicateParentIp(childIpId, parentIpIds[i]); } + $.attachedLicenseTerms[childIpId].add(licenseTermsIds[i]); // link child IP to parent IP with license terms $.parentLicenseTerms[childIpId][parentIpIds[i]] = licenseTermsIds[i]; } diff --git a/test/foundry/integration/flows/royalty/Royalty.t.sol b/test/foundry/integration/flows/royalty/Royalty.t.sol index bb72afdc..78a89266 100644 --- a/test/foundry/integration/flows/royalty/Royalty.t.sol +++ b/test/foundry/integration/flows/royalty/Royalty.t.sol @@ -89,12 +89,7 @@ contract Flows_Integration_Disputes is BaseIntegration { ipAcct[2] = registerIpAccount(address(mockNFT), 2, u.bob); vm.expectRevert( - abi.encodeWithSelector( - Errors.LicenseRegistry__DuplicateLicense.selector, - ipAcct[1], - address(pilTemplate), - commRemixTermsId - ) + abi.encodeWithSelector(Errors.LicenseRegistry__DuplicateParentIp.selector, ipAcct[2], ipAcct[1]) ); licensingModule.registerDerivativeWithLicenseTokens(ipAcct[2], licenseIds, "", 100e6); diff --git a/test/foundry/registries/LicenseRegistry.t.sol b/test/foundry/registries/LicenseRegistry.t.sol index 52942248..38e941db 100644 --- a/test/foundry/registries/LicenseRegistry.t.sol +++ b/test/foundry/registries/LicenseRegistry.t.sol @@ -409,8 +409,15 @@ contract LicenseRegistryTest is BaseTest { }); } - function test_LicenseRegistry_registerDerivativeIp_revert_DuplicateLicense() public { + function test_LicenseRegistry_registerDerivativeIp_revert_DuplicateParents() public { uint256 socialRemixTermsId = pilTemplate.registerLicenseTerms(PILFlavors.nonCommercialSocialRemixing()); + uint256 commRemixTermsId = pilTemplate.registerLicenseTerms( + PILFlavors.commercialRemix(0, 10, address(royaltyPolicyLAP), address(erc20)) + ); + + vm.prank(ipOwner[1]); + licensingModule.attachLicenseTerms(ipAcct[1], address(pilTemplate), commRemixTermsId); + vm.prank(ipOwner[1]); vm.expectRevert( abi.encodeWithSelector( @@ -427,14 +434,9 @@ contract LicenseRegistryTest is BaseTest { parentIpIds[1] = ipAcct[1]; uint256[] memory licenseTermsIds = new uint256[](2); licenseTermsIds[0] = socialRemixTermsId; - licenseTermsIds[1] = socialRemixTermsId; + licenseTermsIds[1] = commRemixTermsId; vm.expectRevert( - abi.encodeWithSelector( - Errors.LicenseRegistry__DuplicateLicense.selector, - ipAcct[1], - address(pilTemplate), - socialRemixTermsId - ) + abi.encodeWithSelector(Errors.LicenseRegistry__DuplicateParentIp.selector, ipAcct[2], ipAcct[1]) ); vm.prank(address(licensingModule)); licenseRegistry.registerDerivativeIp({ From 28d1bf2961aa15619b7443de7068b66250a3e18f Mon Sep 17 00:00:00 2001 From: Spablob <99089658+Spablob@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:46:20 +0000 Subject: [PATCH 2/2] Remove amount input from transferToVault() function (#324) * contract changes to remove amount input from transferToVault * unit test adjustments --- .../policies/IGraphAwareRoyaltyPolicy.sol | 4 +- contracts/lib/Errors.sol | 12 ----- .../royalty/policies/LAP/RoyaltyPolicyLAP.sol | 27 ++++++----- .../royalty/policies/LRP/RoyaltyPolicyLRP.sol | 27 ++++++----- .../integration/flows/grouping/Grouping.t.sol | 7 +-- .../integration/flows/royalty/Royalty.t.sol | 20 +++------ .../mocks/policy/MockRoyaltyPolicyLAP.sol | 2 +- .../modules/grouping/GroupingModule.t.sol | 2 +- .../modules/licensing/LicensingModule.t.sol | 4 +- .../royalty/LAP/RoyaltyPolicyLAP.t.sol | 42 +---------------- .../royalty/LRP/RoyaltyPolicyLRP.t.sol | 45 ++----------------- 11 files changed, 49 insertions(+), 143 deletions(-) diff --git a/contracts/interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol b/contracts/interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol index 8a82277e..a9bccda5 100644 --- a/contracts/interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol +++ b/contracts/interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol @@ -16,8 +16,8 @@ interface IGraphAwareRoyaltyPolicy is IRoyaltyPolicy { /// @param ipId The ipId of the IP asset /// @param ancestorIpId The ancestor ipId of the IP asset /// @param token The token address to transfer - /// @param amount The amount of tokens to transfer - function transferToVault(address ipId, address ancestorIpId, address token, uint256 amount) external; + /// @return The amount of revenue tokens transferred + function transferToVault(address ipId, address ancestorIpId, address token) external returns (uint256); /// @notice Returns the royalty percentage between an IP asset and a given ancestor /// @param ipId The ipId to get the royalty for diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index a62dd5aa..d71c15e0 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -653,15 +653,9 @@ library Errors { /// @notice Zero claimable royalty. error RoyaltyPolicyLAP__ZeroClaimableRoyalty(); - /// @notice Amount exceeds the claimable royalty. - error RoyaltyPolicyLAP__ExceedsClaimableRoyalty(); - /// @notice Above maximum percentage. error RoyaltyPolicyLAP__AboveMaxPercent(); - /// @notice Zero amount provided. - error RoyaltyPolicyLAP__ZeroAmount(); - //////////////////////////////////////////////////////////////////////////// // Royalty Policy LRP // //////////////////////////////////////////////////////////////////////////// @@ -684,15 +678,9 @@ library Errors { /// @notice Zero claimable royalty. error RoyaltyPolicyLRP__ZeroClaimableRoyalty(); - /// @notice Claimer is not an ancestor of the IP. - error RoyaltyPolicyLRP__ExceedsClaimableRoyalty(); - /// @notice Above maximum percentage. error RoyaltyPolicyLRP__AboveMaxPercent(); - /// @notice Zero amount provided. - error RoyaltyPolicyLRP__ZeroAmount(); - //////////////////////////////////////////////////////////////////////////// // IP Royalty Vault // //////////////////////////////////////////////////////////////////////////// diff --git a/contracts/modules/royalty/policies/LAP/RoyaltyPolicyLAP.sol b/contracts/modules/royalty/policies/LAP/RoyaltyPolicyLAP.sol index ddfdc168..46559477 100644 --- a/contracts/modules/royalty/policies/LAP/RoyaltyPolicyLAP.sol +++ b/contracts/modules/royalty/policies/LAP/RoyaltyPolicyLAP.sol @@ -5,6 +5,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { IRoyaltyModule } from "../../../../interfaces/modules/royalty/IRoyaltyModule.sol"; import { IGraphAwareRoyaltyPolicy } from "../../../../interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol"; @@ -124,12 +125,14 @@ contract RoyaltyPolicyLAP is /// @param ipId The ipId of the IP asset /// @param ancestorIpId The ancestor ipId of the IP asset /// @param token The token address to transfer - /// @param amount The amount of tokens to transfer - function transferToVault(address ipId, address ancestorIpId, address token, uint256 amount) external whenNotPaused { + /// @return The amount of revenue tokens transferred + function transferToVault( + address ipId, + address ancestorIpId, + address token + ) external whenNotPaused returns (uint256) { RoyaltyPolicyLAPStorage storage $ = _getRoyaltyPolicyLAPStorage(); - if (amount == 0) revert Errors.RoyaltyPolicyLAP__ZeroAmount(); - uint32 ancestorPercent = $.ancestorPercentLAP[ipId][ancestorIpId]; if (ancestorPercent == 0) { // on the first transfer to a vault from a specific descendant the royalty between the two is set @@ -138,21 +141,21 @@ contract RoyaltyPolicyLAP is $.ancestorPercentLAP[ipId][ancestorIpId] = ancestorPercent; } - // check if the amount being claimed is within the claimable royalty amount + // calculate the amount to transfer IRoyaltyModule royaltyModule = ROYALTY_MODULE; uint256 totalRevenueTokens = royaltyModule.totalRevenueTokensReceived(ipId, token); uint256 maxAmount = (totalRevenueTokens * ancestorPercent) / royaltyModule.maxPercent(); uint256 transferredAmount = $.transferredTokenLAP[ipId][ancestorIpId][token]; - if (transferredAmount + amount > maxAmount) revert Errors.RoyaltyPolicyLAP__ExceedsClaimableRoyalty(); + uint256 amountToTransfer = Math.min(maxAmount - transferredAmount, IERC20(token).balanceOf(address(this))); + // make the revenue token transfer + $.transferredTokenLAP[ipId][ancestorIpId][token] += amountToTransfer; address ancestorIpRoyaltyVault = royaltyModule.ipRoyaltyVaults(ancestorIpId); + IIpRoyaltyVault(ancestorIpRoyaltyVault).updateVaultBalance(token, amountToTransfer); + IERC20(token).safeTransfer(ancestorIpRoyaltyVault, amountToTransfer); - $.transferredTokenLAP[ipId][ancestorIpId][token] += amount; - - IIpRoyaltyVault(ancestorIpRoyaltyVault).updateVaultBalance(token, amount); - IERC20(token).safeTransfer(ancestorIpRoyaltyVault, amount); - - emit RevenueTransferredToVault(ipId, ancestorIpId, token, amount); + emit RevenueTransferredToVault(ipId, ancestorIpId, token, amountToTransfer); + return amountToTransfer; } /// @notice Returns the amount of royalty tokens required to link a child to a given IP asset diff --git a/contracts/modules/royalty/policies/LRP/RoyaltyPolicyLRP.sol b/contracts/modules/royalty/policies/LRP/RoyaltyPolicyLRP.sol index 14aa37ec..ab377135 100644 --- a/contracts/modules/royalty/policies/LRP/RoyaltyPolicyLRP.sol +++ b/contracts/modules/royalty/policies/LRP/RoyaltyPolicyLRP.sol @@ -5,6 +5,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; import { IRoyaltyModule } from "../../../../interfaces/modules/royalty/IRoyaltyModule.sol"; import { IGraphAwareRoyaltyPolicy } from "../../../../interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol"; @@ -151,12 +152,14 @@ contract RoyaltyPolicyLRP is /// @param ipId The ipId of the IP asset /// @param ancestorIpId The ancestor ipId of the IP asset /// @param token The token address to transfer - /// @param amount The amount of tokens to transfer - function transferToVault(address ipId, address ancestorIpId, address token, uint256 amount) external whenNotPaused { + /// @return The amount of revenue tokens transferred + function transferToVault( + address ipId, + address ancestorIpId, + address token + ) external whenNotPaused returns (uint256) { RoyaltyPolicyLRPStorage storage $ = _getRoyaltyPolicyLRPStorage(); - if (amount == 0) revert Errors.RoyaltyPolicyLRP__ZeroAmount(); - uint32 ancestorPercent = $.ancestorPercentLRP[ipId][ancestorIpId]; if (ancestorPercent == 0) { // on the first transfer to a vault from a specific descendant the royalty between the two is set @@ -165,21 +168,21 @@ contract RoyaltyPolicyLRP is $.ancestorPercentLRP[ipId][ancestorIpId] = ancestorPercent; } - // check if the amount being claimed is within the claimable royalty amount + // calculate the amount to transfer IRoyaltyModule royaltyModule = ROYALTY_MODULE; uint256 totalRevenueTokens = royaltyModule.totalRevenueTokensReceived(ipId, token); uint256 maxAmount = (totalRevenueTokens * ancestorPercent) / royaltyModule.maxPercent(); uint256 transferredAmount = $.transferredTokenLRP[ipId][ancestorIpId][token]; - if (transferredAmount + amount > maxAmount) revert Errors.RoyaltyPolicyLRP__ExceedsClaimableRoyalty(); + uint256 amountToTransfer = Math.min(maxAmount - transferredAmount, IERC20(token).balanceOf(address(this))); + // make the revenue token transfer + $.transferredTokenLRP[ipId][ancestorIpId][token] += amountToTransfer; address ancestorIpRoyaltyVault = royaltyModule.ipRoyaltyVaults(ancestorIpId); + IIpRoyaltyVault(ancestorIpRoyaltyVault).updateVaultBalance(token, amountToTransfer); + IERC20(token).safeTransfer(ancestorIpRoyaltyVault, amountToTransfer); - $.transferredTokenLRP[ipId][ancestorIpId][token] += amount; - - IIpRoyaltyVault(ancestorIpRoyaltyVault).updateVaultBalance(token, amount); - IERC20(token).safeTransfer(ancestorIpRoyaltyVault, amount); - - emit RevenueTransferredToVault(ipId, ancestorIpId, token, amount); + emit RevenueTransferredToVault(ipId, ancestorIpId, token, amountToTransfer); + return amountToTransfer; } /// @notice Returns the amount of royalty tokens required to link a child to a given IP asset diff --git a/test/foundry/integration/flows/grouping/Grouping.t.sol b/test/foundry/integration/flows/grouping/Grouping.t.sol index 0fc79a48..a44cead4 100644 --- a/test/foundry/integration/flows/grouping/Grouping.t.sol +++ b/test/foundry/integration/flows/grouping/Grouping.t.sol @@ -142,12 +142,7 @@ contract Flows_Integration_Grouping is BaseIntegration { ERC20[] memory tokens = new ERC20[](1); tokens[0] = mockToken; - royaltyPolicyLAP.transferToVault( - ipAcct[3], - groupId, - address(mockToken), - (10 ether * 10_000_000) / royaltyModule.maxPercent() - ); + royaltyPolicyLAP.transferToVault(ipAcct[3], groupId, address(mockToken)); vm.warp(block.timestamp + 7 days + 1); diff --git a/test/foundry/integration/flows/royalty/Royalty.t.sol b/test/foundry/integration/flows/royalty/Royalty.t.sol index 78a89266..1af765a5 100644 --- a/test/foundry/integration/flows/royalty/Royalty.t.sol +++ b/test/foundry/integration/flows/royalty/Royalty.t.sol @@ -182,18 +182,8 @@ contract Flows_Integration_Disputes is BaseIntegration { uint256 earningsFromMintingFees = 4 * mintingFee; assertEq(mockToken.balanceOf(vault), earningsFromMintingFees); - royaltyPolicyLAP.transferToVault( - ipAcct[2], - ipAcct[1], - address(mockToken), - (1 ether * 10_000_000) / royaltyModule.maxPercent() - ); - royaltyPolicyLAP.transferToVault( - ipAcct[3], - ipAcct[1], - address(mockToken), - (1 ether * 20_000_000) / royaltyModule.maxPercent() - ); + royaltyPolicyLAP.transferToVault(ipAcct[2], ipAcct[1], address(mockToken)); + royaltyPolicyLAP.transferToVault(ipAcct[3], ipAcct[1], address(mockToken)); vm.warp(block.timestamp + 7 days + 1); @@ -205,7 +195,11 @@ contract Flows_Integration_Disputes is BaseIntegration { assertEq( aliceBalanceAfter - aliceBalanceBefore, - earningsFromMintingFees + (1 ether * (10_000_000 + 20_000_000)) / royaltyModule.maxPercent() + earningsFromMintingFees + + (1 ether * 20_000_000) / + royaltyModule.maxPercent() + // 20% of the 1 ether payment made to IPAccount3 + (mintingFee * 10_000_000) / + royaltyModule.maxPercent() // 10% of the 7 ether mintingFee IPAaccount2 received ); } diff --git a/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol b/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol index 4a09858b..a7bfef4b 100644 --- a/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol +++ b/test/foundry/mocks/policy/MockRoyaltyPolicyLAP.sol @@ -44,7 +44,7 @@ contract MockRoyaltyPolicyLAP is IGraphAwareRoyaltyPolicy { function revenueTokenBalances(address ipId, address token) external view returns (uint256) {} function snapshotsClaimed(address ipId, address token, uint256 snapshot) external view returns (bool) {} function snapshotsClaimedCounter(address ipId, address token) external view returns (uint256) {} - function transferToVault(address ipId, address ancestorIpId, address token, uint256 amount) external {} + function transferToVault(address ipId, address ancestorIpId, address token) external returns (uint256) {} function getPolicyRoyalty(address ipId, address ancestorIpId) external view returns (uint32) {} function getAncestorPercent(address ipId, address ancestorIpId) external view returns (uint32) {} function getTransferredTokens(address ipId, address ancestorIpId, address token) external view returns (uint256) {} diff --git a/test/foundry/modules/grouping/GroupingModule.t.sol b/test/foundry/modules/grouping/GroupingModule.t.sol index 964b0a46..99d20744 100644 --- a/test/foundry/modules/grouping/GroupingModule.t.sol +++ b/test/foundry/modules/grouping/GroupingModule.t.sol @@ -274,7 +274,7 @@ contract GroupingModuleTest is BaseTest { erc20.approve(address(royaltyModule), 1000); royaltyModule.payRoyaltyOnBehalf(ipId3, ipOwner3, address(erc20), 1000); vm.stopPrank(); - royaltyPolicyLAP.transferToVault(ipId3, groupId, address(erc20), 100); + royaltyPolicyLAP.transferToVault(ipId3, groupId, address(erc20)); vm.warp(vm.getBlockTimestamp() + 7 days); vm.expectEmit(); diff --git a/test/foundry/modules/licensing/LicensingModule.t.sol b/test/foundry/modules/licensing/LicensingModule.t.sol index c71cd70f..0c42a560 100644 --- a/test/foundry/modules/licensing/LicensingModule.t.sol +++ b/test/foundry/modules/licensing/LicensingModule.t.sol @@ -1819,8 +1819,8 @@ contract LicensingModuleTest is BaseTest { vm.startPrank(ipOwner3); erc20.approve(address(royaltyModule), 1000); royaltyModule.payRoyaltyOnBehalf(ipId3, address(0), address(erc20), 1000); - royaltyPolicyLAP.transferToVault(ipId3, ipId2, address(erc20), 100); - royaltyPolicyLAP.transferToVault(ipId3, ipId1, address(erc20), 10); + royaltyPolicyLAP.transferToVault(ipId3, ipId2, address(erc20)); + royaltyPolicyLAP.transferToVault(ipId3, ipId1, address(erc20)); vm.stopPrank(); assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId2)), 100); assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId1)), 10); diff --git a/test/foundry/modules/royalty/LAP/RoyaltyPolicyLAP.t.sol b/test/foundry/modules/royalty/LAP/RoyaltyPolicyLAP.t.sol index f84e801e..f05382fd 100644 --- a/test/foundry/modules/royalty/LAP/RoyaltyPolicyLAP.t.sol +++ b/test/foundry/modules/royalty/LAP/RoyaltyPolicyLAP.t.sol @@ -179,11 +179,6 @@ contract TestRoyaltyPolicyLAP is BaseTest { assertEq(royaltyPolicyLAP.getPolicyRoyalty(address(80), address(30)), 20 * 10 ** 6); } - function test_RoyaltyPolicyLAP_transferToVault_revert_ZeroAmount() public { - vm.expectRevert(Errors.RoyaltyPolicyLAP__ZeroAmount.selector); - royaltyPolicyLAP.transferToVault(address(80), address(10), address(USDC), 0); - } - function test_RoyaltyPolicyLAP_transferToVault_revert_ZeroClaimableRoyalty() public { address[] memory parents = new address[](3); address[] memory licenseRoyaltyPolicies = new address[](3); @@ -214,42 +209,9 @@ contract TestRoyaltyPolicyLAP is BaseTest { // first transfer to vault vm.expectRevert(Errors.RoyaltyPolicyLAP__ZeroClaimableRoyalty.selector); - royaltyPolicyLAP.transferToVault(ipAccount1, address(2000), address(USDC), 100 * 10 ** 6); + royaltyPolicyLAP.transferToVault(ipAccount1, address(2000), address(USDC)); } - function test_RoyaltyPolicyLAP_transferToVault_revert_ExceedsClaimableRoyalty() public { - address[] memory parents = new address[](3); - address[] memory licenseRoyaltyPolicies = new address[](3); - uint32[] memory parentRoyalties = new uint32[](3); - parents[0] = address(10); - parents[1] = address(20); - parents[2] = address(30); - licenseRoyaltyPolicies[0] = address(royaltyPolicyLAP); - licenseRoyaltyPolicies[1] = address(royaltyPolicyLAP); - licenseRoyaltyPolicies[2] = address(royaltyPolicyLAP); - parentRoyalties[0] = uint32(10 * 10 ** 6); - parentRoyalties[1] = uint32(15 * 10 ** 6); - parentRoyalties[2] = uint32(20 * 10 ** 6); - ipGraph.addParentIp(ipAccount1, parents); - - vm.startPrank(address(licensingModule)); - royaltyModule.onLinkToParents(ipAccount1, parents, licenseRoyaltyPolicies, parentRoyalties, "", 100e6); - - // make payment to ip 80 - uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = ipAccount1; - address payerIpId = address(3); - vm.startPrank(payerIpId); - USDC.mint(payerIpId, royaltyAmount); - USDC.approve(address(royaltyModule), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(receiverIpId, payerIpId, address(USDC), royaltyAmount); - vm.stopPrank(); - - royaltyPolicyLAP.transferToVault(ipAccount1, address(10), address(USDC), 5 * 10 ** 6); - - vm.expectRevert(Errors.RoyaltyPolicyLAP__ExceedsClaimableRoyalty.selector); - royaltyPolicyLAP.transferToVault(ipAccount1, address(10), address(USDC), 6 * 10 ** 6); - } function test_RoyaltyPolicyLAP_transferToVault() public { address[] memory parents = new address[](3); address[] memory licenseRoyaltyPolicies = new address[](3); @@ -288,7 +250,7 @@ contract TestRoyaltyPolicyLAP is BaseTest { vm.expectEmit(true, true, true, true, address(royaltyPolicyLAP)); emit RevenueTransferredToVault(ipAccount1, address(10), address(USDC), 10 * 10 ** 6); - royaltyPolicyLAP.transferToVault(ipAccount1, address(10), address(USDC), 10 * 10 ** 6); + royaltyPolicyLAP.transferToVault(ipAccount1, address(10), address(USDC)); uint256 transferredAmountAfter = royaltyPolicyLAP.getTransferredTokens(ipAccount1, address(10), address(USDC)); uint256 usdcAncestorVaultBalanceAfter = USDC.balanceOf(ancestorIpRoyaltyVault); diff --git a/test/foundry/modules/royalty/LRP/RoyaltyPolicyLRP.t.sol b/test/foundry/modules/royalty/LRP/RoyaltyPolicyLRP.t.sol index b83ead96..1cc1d7cb 100644 --- a/test/foundry/modules/royalty/LRP/RoyaltyPolicyLRP.t.sol +++ b/test/foundry/modules/royalty/LRP/RoyaltyPolicyLRP.t.sol @@ -189,11 +189,6 @@ contract TestRoyaltyPolicyLRP is BaseTest { assertEq(royaltyPolicyLRP.getPolicyRoyalty(address(80), address(30)), 20 * 10 ** 6); } - function test_RoyaltyPolicyLRP_transferToVault_revert_ZeroAmount() public { - vm.expectRevert(Errors.RoyaltyPolicyLRP__ZeroAmount.selector); - royaltyPolicyLRP.transferToVault(address(80), address(10), address(USDC), 0); - } - function test_RoyaltyPolicyLRP_transferToVault_revert_ZeroClaimableRoyalty() public { address[] memory parents = new address[](3); address[] memory licenseRoyaltyPolicies = new address[](3); @@ -223,42 +218,8 @@ contract TestRoyaltyPolicyLRP is BaseTest { vm.stopPrank(); // first transfer to vault - vm.expectRevert(); - royaltyPolicyLRP.transferToVault(ipAccount1, address(10), address(USDC), 100 * 10 ** 6); - } - - function test_RoyaltyPolicyLRP_transferToVault_revert_ExceedsClaimableRoyalty() public { - address[] memory parents = new address[](3); - address[] memory licenseRoyaltyPolicies = new address[](3); - uint32[] memory parentRoyalties = new uint32[](3); - parents[0] = address(10); - parents[1] = address(20); - parents[2] = address(30); - licenseRoyaltyPolicies[0] = address(royaltyPolicyLRP); - licenseRoyaltyPolicies[1] = address(royaltyPolicyLRP); - licenseRoyaltyPolicies[2] = address(royaltyPolicyLRP); - parentRoyalties[0] = uint32(10 * 10 ** 6); - parentRoyalties[1] = uint32(15 * 10 ** 6); - parentRoyalties[2] = uint32(20 * 10 ** 6); - ipGraph.addParentIp(ipAccount1, parents); - - vm.startPrank(address(licensingModule)); - royaltyModule.onLinkToParents(ipAccount1, parents, licenseRoyaltyPolicies, parentRoyalties, "", 100e6); - - // make payment to ip 80 - uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = ipAccount1; - address payerIpId = address(3); - vm.startPrank(payerIpId); - USDC.mint(payerIpId, royaltyAmount); - USDC.approve(address(royaltyModule), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(receiverIpId, payerIpId, address(USDC), royaltyAmount); - vm.stopPrank(); - - royaltyPolicyLRP.transferToVault(ipAccount1, address(10), address(USDC), 5 * 10 ** 6); - - vm.expectRevert(Errors.RoyaltyPolicyLRP__ExceedsClaimableRoyalty.selector); - royaltyPolicyLRP.transferToVault(ipAccount1, address(10), address(USDC), 6 * 10 ** 6); + vm.expectRevert(); // throws out-of-gas instead of ZeroClaimableRoyalty due to using the mock ip graph + royaltyPolicyLRP.transferToVault(ipAccount1, address(2000), address(USDC)); } function test_RoyaltyPolicyLRP_transferToVault() public { @@ -299,7 +260,7 @@ contract TestRoyaltyPolicyLRP is BaseTest { uint256 usdcAncestorVaultBalanceBefore = USDC.balanceOf(ancestorIpRoyaltyVault); uint256 usdcLRPContractBalanceBefore = USDC.balanceOf(address(royaltyPolicyLRP)); - royaltyPolicyLRP.transferToVault(ipAccount1, address(10), address(USDC), 10 * 10 ** 6); + royaltyPolicyLRP.transferToVault(ipAccount1, address(10), address(USDC)); uint256 transferredAmountAfter = royaltyPolicyLRP.getTransferredTokens(ipAccount1, address(10), address(USDC)); uint256 usdcAncestorVaultBalanceAfter = USDC.balanceOf(ancestorIpRoyaltyVault);