diff --git a/contracts/interfaces/modules/dispute/policies/IArbitrationPolicy.sol b/contracts/interfaces/modules/dispute/policies/IArbitrationPolicy.sol index fc067d933..738549168 100644 --- a/contracts/interfaces/modules/dispute/policies/IArbitrationPolicy.sol +++ b/contracts/interfaces/modules/dispute/policies/IArbitrationPolicy.sol @@ -7,7 +7,7 @@ interface IArbitrationPolicy { /// @param amount The amount withdrawn event GovernanceWithdrew(uint256 amount); - /// @notice Returns the dispute module address + /// @notice Returns the protocol-wide dispute module address function DISPUTE_MODULE() external view returns (address); /// @notice Returns the payment token address diff --git a/contracts/interfaces/modules/royalty/IRoyaltyModule.sol b/contracts/interfaces/modules/royalty/IRoyaltyModule.sol index 99ba838ab..f0216ce95 100644 --- a/contracts/interfaces/modules/royalty/IRoyaltyModule.sol +++ b/contracts/interfaces/modules/royalty/IRoyaltyModule.sol @@ -35,17 +35,9 @@ interface IRoyaltyModule is IModule { /// @param licensing The address of the license module function setLicensingModule(address licensing) external; - /// @notice Sets the dispute module - /// @dev Enforced to be only callable by the protocol admin - /// @param dispute The address of the dispute module - function setDisputeModule(address dispute) external; - /// @notice Returns the licensing module address function licensingModule() external view returns (address); - /// @notice Returns the dispute module address - function disputeModule() external view returns (address); - /// @notice Indicates if a royalty policy is whitelisted /// @param royaltyPolicy The address of the royalty policy /// @return isWhitelisted True if the royalty policy is whitelisted diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index cb559878d..97e8ac259 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -278,6 +278,8 @@ library Errors { error RoyaltyModule__CanOnlyMintSelectedPolicy(); error RoyaltyModule__NoParentsOnLinking(); error RoyaltyModule__ZeroDisputeModule(); + error RoyaltyModule__ZeroLicenseRegistry(); + error RoyaltyModule__IpIsExpired(); error RoyaltyModule__IpIsTagged(); error RoyaltyModule__ZeroAccessManager(); diff --git a/contracts/modules/dispute/policies/ArbitrationPolicySP.sol b/contracts/modules/dispute/policies/ArbitrationPolicySP.sol index d5c93074e..20e42d621 100644 --- a/contracts/modules/dispute/policies/ArbitrationPolicySP.sol +++ b/contracts/modules/dispute/policies/ArbitrationPolicySP.sol @@ -17,7 +17,7 @@ import { Errors } from "../../../lib/Errors.sol"; contract ArbitrationPolicySP is IArbitrationPolicy, AccessManagedUpgradeable, UUPSUpgradeable { using SafeERC20 for IERC20; - /// @notice Returns the dispute module address + /// @notice Returns the protocol-wide dispute module address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address public immutable DISPUTE_MODULE; /// @notice Returns the payment token address diff --git a/contracts/modules/licensing/LicensingModule.sol b/contracts/modules/licensing/LicensingModule.sol index 1d7873ecf..0a48e7567 100644 --- a/contracts/modules/licensing/LicensingModule.sol +++ b/contracts/modules/licensing/LicensingModule.sol @@ -60,7 +60,7 @@ contract LicensingModule is /// @custom:oz-upgrades-unsafe-allow state-variable-immutable ILicenseRegistry public immutable LICENSE_REGISTRY; - /// @notice Returns the dispute module + /// @notice Returns the protocol-wide dispute module /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IDisputeModule public immutable DISPUTE_MODULE; diff --git a/contracts/modules/royalty/RoyaltyModule.sol b/contracts/modules/royalty/RoyaltyModule.sol index df328641a..7510511e3 100644 --- a/contracts/modules/royalty/RoyaltyModule.sol +++ b/contracts/modules/royalty/RoyaltyModule.sol @@ -12,6 +12,7 @@ import { BaseModule } from "../BaseModule.sol"; import { IRoyaltyModule } from "../../interfaces/modules/royalty/IRoyaltyModule.sol"; import { IRoyaltyPolicy } from "../../interfaces/modules/royalty/policies/IRoyaltyPolicy.sol"; import { IDisputeModule } from "../../interfaces/modules/dispute/IDisputeModule.sol"; +import { ILicenseRegistry } from "../../interfaces/registries/ILicenseRegistry.sol"; import { Errors } from "../../lib/Errors.sol"; import { ROYALTY_MODULE_KEY } from "../../lib/modules/Module.sol"; import { BaseModule } from "../BaseModule.sol"; @@ -28,15 +29,21 @@ contract RoyaltyModule is { using ERC165Checker for address; + /// @notice Returns the canonical protocol-wide LicenseRegistry + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + ILicenseRegistry public immutable LICENSE_REGISTRY; + + /// @notice Returns the protocol-wide dispute module + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + IDisputeModule public immutable DISPUTE_MODULE; + /// @dev Storage structure for the RoyaltyModule - /// @param disputeModule The address of the dispute module /// @param licensingModule The address of the licensing module /// @param isWhitelistedRoyaltyPolicy Indicates if a royalty policy is whitelisted /// @param isWhitelistedRoyaltyToken Indicates if a royalty token is whitelisted /// @param royaltyPolicies Indicates the royalty policy for a given IP asset /// @custom:storage-location erc7201:story-protocol.RoyaltyModule struct RoyaltyModuleStorage { - address disputeModule; address licensingModule; mapping(address royaltyPolicy => bool isWhitelisted) isWhitelistedRoyaltyPolicy; mapping(address token => bool) isWhitelistedRoyaltyToken; @@ -50,8 +57,15 @@ contract RoyaltyModule is string public constant override name = ROYALTY_MODULE_KEY; /// @notice Constructor + /// @param disputeModule The address of the dispute module + /// @param licenseRegistry The address of the license registry /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { + constructor(address disputeModule, address licenseRegistry) { + if (disputeModule == address(0)) revert Errors.RoyaltyModule__ZeroDisputeModule(); + if (licenseRegistry == address(0)) revert Errors.RoyaltyModule__ZeroLicenseRegistry(); + + DISPUTE_MODULE = IDisputeModule(disputeModule); + LICENSE_REGISTRY = ILicenseRegistry(licenseRegistry); _disableInitializers(); } @@ -81,14 +95,6 @@ contract RoyaltyModule is _getRoyaltyModuleStorage().licensingModule = licensing; } - /// @notice Sets the dispute module - /// @dev Enforced to be only callable by the protocol admin - /// @param dispute The address of the dispute module - function setDisputeModule(address dispute) external restricted { - if (dispute == address(0)) revert Errors.RoyaltyModule__ZeroDisputeModule(); - _getRoyaltyModuleStorage().disputeModule = dispute; - } - /// @notice Whitelist a royalty policy /// @dev Enforced to be only callable by the protocol admin /// @param royaltyPolicy The address of the royalty policy @@ -190,7 +196,7 @@ contract RoyaltyModule is RoyaltyModuleStorage storage $ = _getRoyaltyModuleStorage(); if (!$.isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken(); - IDisputeModule dispute = IDisputeModule($.disputeModule); + IDisputeModule dispute = DISPUTE_MODULE; if (dispute.isIpTagged(receiverIpId) || dispute.isIpTagged(payerIpId)) revert Errors.RoyaltyModule__IpIsTagged(); @@ -201,6 +207,10 @@ contract RoyaltyModule is if (!$.isWhitelistedRoyaltyPolicy[payerRoyaltyPolicy]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy(); + ILicenseRegistry licenseRegistry = LICENSE_REGISTRY; + if (licenseRegistry.isExpiredNow(receiverIpId) || licenseRegistry.isExpiredNow(payerIpId)) + revert Errors.RoyaltyModule__IpIsExpired(); + IRoyaltyPolicy(payerRoyaltyPolicy).onRoyaltyPayment(msg.sender, receiverIpId, token, amount); emit RoyaltyPaid(receiverIpId, payerIpId, msg.sender, token, amount); @@ -221,10 +231,11 @@ contract RoyaltyModule is ) external onlyLicensingModule { RoyaltyModuleStorage storage $ = _getRoyaltyModuleStorage(); if (!$.isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken(); - if (IDisputeModule($.disputeModule).isIpTagged(receiverIpId)) revert Errors.RoyaltyModule__IpIsTagged(); + if (DISPUTE_MODULE.isIpTagged(receiverIpId)) revert Errors.RoyaltyModule__IpIsTagged(); if (licenseRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet(); if (!$.isWhitelistedRoyaltyPolicy[licenseRoyaltyPolicy]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy(); + if (LICENSE_REGISTRY.isExpiredNow(receiverIpId)) revert Errors.RoyaltyModule__IpIsExpired(); IRoyaltyPolicy(licenseRoyaltyPolicy).onRoyaltyPayment(payerAddress, receiverIpId, token, amount); @@ -236,11 +247,6 @@ contract RoyaltyModule is return _getRoyaltyModuleStorage().licensingModule; } - /// @notice Returns the dispute module address - function disputeModule() external view returns (address) { - return _getRoyaltyModuleStorage().disputeModule; - } - /// @notice Indicates if a royalty policy is whitelisted /// @param royaltyPolicy The address of the royalty policy /// @return isWhitelisted True if the royalty policy is whitelisted diff --git a/script/foundry/utils/DeployHelper.sol b/script/foundry/utils/DeployHelper.sol index 4410083b7..bbc485a98 100644 --- a/script/foundry/utils/DeployHelper.sol +++ b/script/foundry/utils/DeployHelper.sol @@ -213,18 +213,6 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag IPAccountRegistry ipAccountRegistry = IPAccountRegistry(address(ipAssetRegistry)); - contractKey = "RoyaltyModule"; - _predeploy(contractKey); - impl = address(new RoyaltyModule()); - royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) - ) - ); - impl = address(0); - _postdeploy(contractKey, address(royaltyModule)); - contractKey = "LicenseRegistry"; _predeploy(contractKey); impl = address(new LicenseRegistry()); @@ -267,6 +255,18 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag impl = address(0); _postdeploy(contractKey, address(licenseToken)); + contractKey = "RoyaltyModule"; + _predeploy(contractKey); + impl = address(new RoyaltyModule(address(disputeModule), address(licenseRegistry))); + royaltyModule = RoyaltyModule( + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) + ) + ); + impl = address(0); + _postdeploy(contractKey, address(royaltyModule)); + contractKey = "LicensingModule"; _predeploy(contractKey); impl = address( @@ -396,7 +396,6 @@ contract DeployHelper is Script, BroadcastManager, JsonDeploymentHandler, Storag // Royalty Module and SP Royalty Policy royaltyModule.setLicensingModule(address(licensingModule)); - royaltyModule.setDisputeModule(address(disputeModule)); royaltyModule.whitelistRoyaltyPolicy(address(royaltyPolicyLAP), true); royaltyModule.whitelistRoyaltyToken(address(erc20), true); royaltyPolicyLAP.setSnapshotInterval(7 days); diff --git a/test/foundry/integration/flows/licensing/LicensingIntegration.t.sol b/test/foundry/integration/flows/licensing/LicensingIntegration.t.sol index 72efac65b..902e0da58 100644 --- a/test/foundry/integration/flows/licensing/LicensingIntegration.t.sol +++ b/test/foundry/integration/flows/licensing/LicensingIntegration.t.sol @@ -116,15 +116,6 @@ contract e2e is Test { ) ); - impl = address(new RoyaltyModule()); - royaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall(RoyaltyModule.initialize, (address(protocolAccessManager))) - ) - ); - vm.label(address(royaltyModule), "RoyaltyModule"); - impl = address( new DisputeModule(address(accessController), address(ipAssetRegistry), address(licenseRegistry)) ); @@ -136,6 +127,16 @@ contract e2e is Test { ) ); + + impl = address(new RoyaltyModule(address(disputeModule), address(licenseRegistry))); + royaltyModule = RoyaltyModule( + TestProxyHelper.deployUUPSProxy( + impl, + abi.encodeCall(RoyaltyModule.initialize, (address(protocolAccessManager))) + ) + ); + vm.label(address(royaltyModule), "RoyaltyModule"); + impl = address( new LicensingModule( address(accessController), @@ -211,7 +212,6 @@ contract e2e is Test { moduleRegistry.registerModule(ROYALTY_MODULE_KEY, address(royaltyModule)); royaltyModule.setLicensingModule(address(licensingModule)); - royaltyModule.setDisputeModule(address(disputeModule)); royaltyModule.whitelistRoyaltyToken(address(erc20), true); royaltyModule.whitelistRoyaltyPolicy(address(royaltyPolicyLAP), true); diff --git a/test/foundry/modules/royalty/IpRoyaltyVault.t.sol b/test/foundry/modules/royalty/IpRoyaltyVault.t.sol index 4e3b91cdd..46ba9a82f 100644 --- a/test/foundry/modules/royalty/IpRoyaltyVault.t.sol +++ b/test/foundry/modules/royalty/IpRoyaltyVault.t.sol @@ -46,7 +46,7 @@ contract TestIpRoyaltyVault is BaseTest { uint32[] memory parentRoyalties1 = new uint32[](2); bytes[] memory encodedLicenseData = new bytes[](2); - // 3 is child of 7 and 8 + // 100 is child of 7 and 8 parents[0] = address(7); parents[1] = address(8); parentRoyalties1[0] = 7 * 10 ** 5; @@ -55,7 +55,7 @@ contract TestIpRoyaltyVault is BaseTest { for (uint32 i = 0; i < parentRoyalties1.length; i++) { encodedLicenseData[i] = abi.encode(parentRoyalties1[i]); } - royaltyPolicyLAP.onLinkToParents(address(3), parents, encodedLicenseData, ""); + royaltyPolicyLAP.onLinkToParents(address(100), parents, encodedLicenseData, ""); // 4 is child of 9 and 10 parents[0] = address(9); @@ -91,8 +91,8 @@ contract TestIpRoyaltyVault is BaseTest { royaltyPolicyLAP.onLinkToParents(address(6), parents, encodedLicenseData, ""); // init 3rd level with children - // 1 is child of 3 and 4 - parents[0] = address(3); + // 1 is child of 100 and 4 + parents[0] = address(100); parents[1] = address(4); parentRoyalties1[0] = 3 * 10 ** 5; parentRoyalties1[1] = 4 * 10 ** 5; @@ -128,8 +128,7 @@ contract TestIpRoyaltyVault is BaseTest { } vm.startPrank(address(licensingModule)); - royaltyModule.onLinkToParents(address(100), address(royaltyPolicyLAP), parents, encodedLicenseData, ""); - //royaltyPolicyLAP.onLinkToParents(address(100), parents, encodedLicenseData, ""); + royaltyModule.onLinkToParents(address(3), address(royaltyPolicyLAP), parents, encodedLicenseData, ""); } function test_IpRoyaltyVault_AddIpRoyaltyVaultTokens_NotRoyaltyPolicyLAP() public { @@ -150,10 +149,10 @@ contract TestIpRoyaltyVault is BaseTest { function test_IpRoyaltyVault_ClaimableRevenue() public { // payment is made to vault uint256 royaltyAmount = 100000 * 10 ** 6; - USDC.mint(address(100), 100000 * 10 ** 6); // 100k USDC - vm.startPrank(address(100)); + USDC.mint(address(3), 100000 * 10 ** 6); // 100k USDC + vm.startPrank(address(3)); USDC.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount); vm.stopPrank(); // take snapshot @@ -172,13 +171,13 @@ contract TestIpRoyaltyVault is BaseTest { function test_IpRoyaltyVault_ClaimRevenueByTokenBatch() public { // payment is made to vault uint256 royaltyAmount = 100000 * 10 ** 6; - USDC.mint(address(100), royaltyAmount); // 100k USDC - LINK.mint(address(100), royaltyAmount); // 100k LINK - vm.startPrank(address(100)); + USDC.mint(address(3), royaltyAmount); // 100k USDC + LINK.mint(address(3), royaltyAmount); // 100k LINK + vm.startPrank(address(3)); USDC.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount); LINK.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(LINK), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(LINK), royaltyAmount); vm.stopPrank(); // take snapshot @@ -220,19 +219,19 @@ contract TestIpRoyaltyVault is BaseTest { function test_IpRoyaltyVault_ClaimRevenueBySnapshotBatch() public { uint256 royaltyAmount = 100000 * 10 ** 6; - USDC.mint(address(100), royaltyAmount); // 100k USDC + USDC.mint(address(3), royaltyAmount); // 100k USDC // 1st payment is made to vault - vm.startPrank(address(100)); + vm.startPrank(address(3)); USDC.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount / 2); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount / 2); // take snapshot vm.warp(block.timestamp + 7 days + 1); ipRoyaltyVault.snapshot(); // 2nt payment is made to vault - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount / 2); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount / 2); vm.stopPrank(); // take snapshot @@ -272,13 +271,13 @@ contract TestIpRoyaltyVault is BaseTest { function test_IpRoyaltyVault_Snapshot() public { // payment is made to vault uint256 royaltyAmount = 100000 * 10 ** 6; - USDC.mint(address(100), royaltyAmount); // 100k USDC - LINK.mint(address(100), royaltyAmount); // 100k LINK - vm.startPrank(address(100)); + USDC.mint(address(3), royaltyAmount); // 100k USDC + LINK.mint(address(3), royaltyAmount); // 100k LINK + vm.startPrank(address(3)); USDC.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount); LINK.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(LINK), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(LINK), royaltyAmount); vm.stopPrank(); // take snapshot @@ -371,10 +370,10 @@ contract TestIpRoyaltyVault is BaseTest { uint256 accruedCollectableRevenue = (royaltyAmount * 5 * 10 ** 5) / royaltyPolicyLAP.TOTAL_RT_SUPPLY(); // payment is made to vault - USDC.mint(address(100), royaltyAmount); // 100k USDC - vm.startPrank(address(100)); + USDC.mint(address(3), royaltyAmount); // 100k USDC + vm.startPrank(address(3)); USDC.approve(address(royaltyPolicyLAP), royaltyAmount); - royaltyModule.payRoyaltyOnBehalf(address(2), address(100), address(USDC), royaltyAmount); + royaltyModule.payRoyaltyOnBehalf(address(2), address(3), address(USDC), royaltyAmount); vm.stopPrank(); // take snapshot diff --git a/test/foundry/modules/royalty/RoyaltyModule.t.sol b/test/foundry/modules/royalty/RoyaltyModule.t.sol index bf170fc7c..52ae10e3c 100644 --- a/test/foundry/modules/royalty/RoyaltyModule.t.sol +++ b/test/foundry/modules/royalty/RoyaltyModule.t.sol @@ -89,7 +89,7 @@ contract TestRoyaltyModule is BaseTest { function _setupTree() internal { // init royalty policy for roots - royaltyModule.onLicenseMinting(address(7), address(royaltyPolicyLAP), abi.encode(uint32(7)), ""); + royaltyModule.onLicenseMinting(address(2), address(royaltyPolicyLAP), abi.encode(uint32(7)), ""); royaltyModule.onLicenseMinting(address(8), address(royaltyPolicyLAP), abi.encode(uint32(8)), ""); // init 2nd level with children @@ -97,8 +97,8 @@ contract TestRoyaltyModule is BaseTest { uint32[] memory parentRoyalties = new uint32[](2); bytes[] memory encodedLicenseData = new bytes[](2); - // 3 is child of 7 and 8 - parents[0] = address(7); + // 3 is child of 2 and 8 + parents[0] = address(2); parents[1] = address(8); parentRoyalties[0] = 7; parentRoyalties[1] = 8; @@ -108,37 +108,11 @@ contract TestRoyaltyModule is BaseTest { royaltyModule.onLinkToParents(address(3), address(royaltyPolicyLAP), parents, encodedLicenseData, ""); } function test_RoyaltyModule_initialize_revert_ZeroAccessManager() public { - address impl = address(new RoyaltyModule()); + address impl = address(new RoyaltyModule(address(disputeModule), address(licenseRegistry))); vm.expectRevert(Errors.RoyaltyModule__ZeroAccessManager.selector); RoyaltyModule(TestProxyHelper.deployUUPSProxy(impl, abi.encodeCall(RoyaltyModule.initialize, address(0)))); } - function test_RoyaltyModule_setDisputeModule_revert_ZeroDisputeModule() public { - address impl = address(new RoyaltyModule()); - RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) - ) - ); - vm.expectRevert(Errors.RoyaltyModule__ZeroDisputeModule.selector); - vm.prank(u.admin); - testRoyaltyModule.setDisputeModule(address(0)); - } - - function test_RoyaltyModule_setDisputeModule() public { - vm.startPrank(u.admin); - address impl = address(new RoyaltyModule()); - RoyaltyModule testRoyaltyModule = RoyaltyModule( - TestProxyHelper.deployUUPSProxy( - impl, - abi.encodeCall(RoyaltyModule.initialize, address(protocolAccessManager)) - ) - ); - testRoyaltyModule.setDisputeModule(address(disputeModule)); - assertEq(testRoyaltyModule.disputeModule(), address(disputeModule)); - } - function test_RoyaltyModule_setLicensingModule_revert_ZeroLicensingModule() public { vm.startPrank(u.admin); vm.expectRevert(Errors.RoyaltyModule__ZeroLicensingModule.selector); @@ -147,7 +121,7 @@ contract TestRoyaltyModule is BaseTest { function test_RoyaltyModule_setLicensingModule() public { vm.startPrank(u.admin); - address impl = address(new RoyaltyModule()); + address impl = address(new RoyaltyModule(address(disputeModule), address(licenseRegistry))); RoyaltyModule testRoyaltyModule = RoyaltyModule( TestProxyHelper.deployUUPSProxy( impl, @@ -226,7 +200,7 @@ contract TestRoyaltyModule is BaseTest { } function test_RoyaltyModule_onLicenseMinting_Root() public { - address licensor = address(7); + address licensor = address(2); bytes memory licenseData = abi.encode(uint32(15)); // mint a license of another policy @@ -247,7 +221,7 @@ contract TestRoyaltyModule is BaseTest { address[] memory parents = new address[](2); uint32[] memory parentRoyalties = new uint32[](2); bytes[] memory encodedLicenseData = new bytes[](2); - parents[0] = address(7); + parents[0] = address(2); parents[1] = address(8); parentRoyalties[0] = 7; parentRoyalties[1] = 8; @@ -300,7 +274,7 @@ contract TestRoyaltyModule is BaseTest { address[] memory parents = new address[](2); uint32[] memory parentRoyalties = new uint32[](2); bytes[] memory encodedLicenseData = new bytes[](2); - parents[0] = address(7); + parents[0] = address(2); parents[1] = address(8); parentRoyalties[0] = 7; parentRoyalties[1] = 8; @@ -321,7 +295,7 @@ contract TestRoyaltyModule is BaseTest { function test_RoyaltyModule_payRoyaltyOnBehalf_revert_NotWhitelistedRoyaltyToken() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerIpId = address(3); vm.expectRevert(Errors.RoyaltyModule__NotWhitelistedRoyaltyToken.selector); @@ -348,7 +322,7 @@ contract TestRoyaltyModule is BaseTest { function test_RoyaltyModule_payRoyaltyOnBehalf_revert_NotWhitelistedRoyaltyPolicy() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerIpId = address(3); vm.startPrank(u.admin); @@ -358,9 +332,26 @@ contract TestRoyaltyModule is BaseTest { royaltyModule.payRoyaltyOnBehalf(receiverIpId, payerIpId, address(USDC), royaltyAmount); } + function test_RoyaltyModule_payRoyaltyOnBehalf_revert_IpIsExpired() public { + uint256 royaltyAmount = 100 * 10 ** 6; + address receiverIpId = address(2); + address payerIpId = address(3); + + (, address ipRoyaltyVault, , , ) = royaltyPolicyLAP.getRoyaltyData(receiverIpId); + + vm.startPrank(payerIpId); + USDC.mint(payerIpId, royaltyAmount); + USDC.approve(address(royaltyPolicyLAP), royaltyAmount); + + vm.warp(block.timestamp + licenseRegistry.getExpireTime(receiverIpId) + 1); + + vm.expectRevert(Errors.RoyaltyModule__IpIsExpired.selector); + royaltyModule.payRoyaltyOnBehalf(receiverIpId, payerIpId, address(USDC), royaltyAmount); + } + function test_RoyaltyModule_payRoyaltyOnBehalf() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerIpId = address(3); (, address ipRoyaltyVault, , , ) = royaltyPolicyLAP.getRoyaltyData(receiverIpId); @@ -400,9 +391,10 @@ contract TestRoyaltyModule is BaseTest { vm.expectRevert(Errors.RoyaltyModule__IpIsTagged.selector); royaltyModule.payLicenseMintingFee(ipAddr, ipAccount1, address(royaltyPolicyLAP), address(USDC), 100); } + function test_RoyaltyModule_payLicenseMintingFee_revert_NotWhitelistedRoyaltyToken() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerAddress = address(3); address licenseRoyaltyPolicy = address(royaltyPolicyLAP); address token = address(1); @@ -410,9 +402,10 @@ contract TestRoyaltyModule is BaseTest { vm.expectRevert(Errors.RoyaltyModule__NotWhitelistedRoyaltyToken.selector); royaltyModule.payLicenseMintingFee(receiverIpId, payerAddress, licenseRoyaltyPolicy, token, royaltyAmount); } + function test_RoyaltyModule_payLicenseMintingFee_revert_NotWhitelistedRoyaltyPolicy() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerAddress = address(3); address licenseRoyaltyPolicy = address(1); address token = address(USDC); @@ -422,9 +415,31 @@ contract TestRoyaltyModule is BaseTest { vm.expectRevert(Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy.selector); royaltyModule.payLicenseMintingFee(receiverIpId, payerAddress, licenseRoyaltyPolicy, token, royaltyAmount); } + + function test_RoyaltyModule_payLicenseMintingFee_revert_IpIsExpired() public { + uint256 royaltyAmount = 100 * 10 ** 6; + address receiverIpId = address(2); + address payerAddress = address(3); + address licenseRoyaltyPolicy = address(royaltyPolicyLAP); + address token = address(USDC); + + (, address ipRoyaltyVault, , , ) = royaltyPolicyLAP.getRoyaltyData(receiverIpId); + + vm.startPrank(payerAddress); + USDC.mint(payerAddress, royaltyAmount); + USDC.approve(address(royaltyPolicyLAP), royaltyAmount); + vm.stopPrank; + + vm.warp(block.timestamp + licenseRegistry.getExpireTime(receiverIpId) + 1); + + vm.startPrank(address(licensingModule)); + vm.expectRevert(Errors.RoyaltyModule__IpIsExpired.selector); + royaltyModule.payLicenseMintingFee(receiverIpId, payerAddress, licenseRoyaltyPolicy, token, royaltyAmount); + } + function test_RoyaltyModule_payLicenseMintingFee() public { uint256 royaltyAmount = 100 * 10 ** 6; - address receiverIpId = address(7); + address receiverIpId = address(2); address payerAddress = address(3); address licenseRoyaltyPolicy = address(royaltyPolicyLAP); address token = address(USDC);