diff --git a/contracts/interfaces/modules/base/IHookModule.sol b/contracts/interfaces/modules/base/IHookModule.sol index 7c8833461..6aa5f20f9 100644 --- a/contracts/interfaces/modules/base/IHookModule.sol +++ b/contracts/interfaces/modules/base/IHookModule.sol @@ -8,4 +8,7 @@ import { IModule } from "./IModule.sol"; interface IHookModule is IModule { /// @notice Verify if the caller is qualified function verify(address caller, bytes calldata data) external returns (bool); + /// @notice Validates the configuration for the hook. + /// @param configData The configuration data for the hook. + function validateConfig(bytes calldata configData) external view; } diff --git a/contracts/interfaces/modules/licensing/IUMLPolicyFrameworkManager.sol b/contracts/interfaces/modules/licensing/IUMLPolicyFrameworkManager.sol index e280140f7..a63a4c9ef 100644 --- a/contracts/interfaces/modules/licensing/IUMLPolicyFrameworkManager.sol +++ b/contracts/interfaces/modules/licensing/IUMLPolicyFrameworkManager.sol @@ -8,8 +8,8 @@ import { IPolicyFrameworkManager } from "../../../interfaces/modules/licensing/I /// @param attribution Whether or not attribution is required when reproducing the work /// @param commercialUse Whether or not the work can be used commercially /// @param commercialAttribution Whether or not attribution is required when reproducing the work commercially -/// @param commercializers List of commericializers that are allowed to commercially exploit the work. If empty -/// then no restrictions. +/// @param commercializerChecker commericializers that are allowed to commercially exploit the work. If zero +/// address then no restrictions. /// @param commercialRevShare Percentage of revenue that must be shared with the licensor /// @param derivativesAllowed Whether or not the licensee can create derivatives of his work /// @param derivativesAttribution Whether or not attribution is required for derivatives of the work @@ -25,8 +25,8 @@ struct UMLPolicy { bool attribution; bool commercialUse; bool commercialAttribution; - address[] commercializers; - bytes[] commercializersData; + address commercializerChecker; + bytes commercializerCheckerData; uint32 commercialRevShare; bool derivativesAllowed; bool derivativesAttribution; diff --git a/contracts/lib/Errors.sol b/contracts/lib/Errors.sol index 3f1313f77..bd1b9f7d3 100644 --- a/contracts/lib/Errors.sol +++ b/contracts/lib/Errors.sol @@ -161,7 +161,7 @@ library Errors { //////////////////////////////////////////////////////////////////////////// error PolicyFrameworkManager__GettingPolicyWrongFramework(); - error PolicyFrameworkManager__CommercializerDoesNotSupportHook(address commercializer); + error PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook(address commercializer); //////////////////////////////////////////////////////////////////////////// // LicensorApprovalChecker // diff --git a/contracts/lib/UMLFrameworkErrors.sol b/contracts/lib/UMLFrameworkErrors.sol index 93683bd65..2e679f668 100644 --- a/contracts/lib/UMLFrameworkErrors.sol +++ b/contracts/lib/UMLFrameworkErrors.sol @@ -25,5 +25,4 @@ library UMLFrameworkErrors { error UMLPolicyFrameworkManager__CommercialValueMismatch(); error UMLPolicyFrameworkManager__DerivativesValueMismatch(); error UMLPolicyFrameworkManager__StringArrayMismatch(); - error UMLPolicyFrameworkManager__CommercializersDataMismatch(); } diff --git a/contracts/modules/licensing/LicensingModule.sol b/contracts/modules/licensing/LicensingModule.sol index ac1d2d7eb..f12b7c8f6 100644 --- a/contracts/modules/licensing/LicensingModule.sol +++ b/contracts/modules/licensing/LicensingModule.sol @@ -6,6 +6,7 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import { IIPAccount } from "../../interfaces/IIPAccount.sol"; import { IPolicyFrameworkManager } from "../../interfaces/modules/licensing/IPolicyFrameworkManager.sol"; @@ -22,7 +23,7 @@ import { LICENSING_MODULE_KEY } from "../../lib/modules/Module.sol"; import { BaseModule } from "../BaseModule.sol"; // TODO: consider disabling operators/approvals on creation -contract LicensingModule is AccessControlled, ILicensingModule, BaseModule { +contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, ReentrancyGuard { using ERC165Checker for address; using IPAccountChecker for IIPAccountRegistry; using EnumerableSet for EnumerableSet.UintSet; @@ -122,7 +123,10 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule { /// @param ipId to receive the policy /// @param polId id of the policy data /// @return indexOnIpId position of policy within the ipIds policy set - function addPolicyToIp(address ipId, uint256 polId) external verifyPermission(ipId) returns (uint256 indexOnIpId) { + function addPolicyToIp( + address ipId, + uint256 polId + ) external nonReentrant verifyPermission(ipId) returns (uint256 indexOnIpId) { if (!isPolicyDefined(polId)) { revert Errors.LicensingModule__PolicyNotFound(); } @@ -166,7 +170,7 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule { address licensorIp, uint256 amount, // mint amount address receiver - ) external returns (uint256 licenseId) { + ) external nonReentrant returns (uint256 licenseId) { // TODO: check if licensor has been tagged by disputer if (!IP_ACCOUNT_REGISTRY.isIpAccount(licensorIp)) { revert Errors.LicensingModule__LicensorNotRegistered(); @@ -257,7 +261,7 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule { uint256[] calldata licenseIds, address childIpId, uint32 minRoyalty - ) external verifyPermission(childIpId) { + ) external nonReentrant verifyPermission(childIpId) { address holder = IIPAccount(payable(childIpId)).owner(); address[] memory licensors = new address[](licenseIds.length); // If royalty policy address is address(0), this means no royalty policy to set. diff --git a/contracts/modules/licensing/UMLPolicyFrameworkManager.sol b/contracts/modules/licensing/UMLPolicyFrameworkManager.sol index d927107c2..15d009ddf 100644 --- a/contracts/modules/licensing/UMLPolicyFrameworkManager.sol +++ b/contracts/modules/licensing/UMLPolicyFrameworkManager.sol @@ -6,6 +6,7 @@ pragma solidity ^0.8.23; import { Base64 } from "@openzeppelin/contracts/utils/Base64.sol"; import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; // contracts import { IHookModule } from "../../interfaces/modules/base/IHookModule.sol"; @@ -23,7 +24,12 @@ import { LicensorApprovalChecker } from "../../modules/licensing/parameter-helpe /// @notice This is the UML Policy Framework Manager, which implements the UML Policy Framework /// logic for encoding and decoding UML policies into the LicenseRegistry and verifying /// the licensing parameters for linking, minting, and transferring. -contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFrameworkManager, LicensorApprovalChecker { +contract UMLPolicyFrameworkManager is + IUMLPolicyFrameworkManager, + BasePolicyFrameworkManager, + LicensorApprovalChecker, + ReentrancyGuard +{ using ERC165Checker for address; using Strings for *; @@ -44,7 +50,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram /// @notice Re a new policy to the registry /// @dev Must encode the policy into bytes to be stored in the LicensingModule /// @param umlPolicy UMLPolicy compliant licensing term values - function registerPolicy(UMLPolicy calldata umlPolicy) external returns (uint256 policyId) { + function registerPolicy(UMLPolicy calldata umlPolicy) external nonReentrant returns (uint256 policyId) { _verifyComercialUse(umlPolicy); _verifyDerivatives(umlPolicy); // No need to emit here, as the LicensingModule will emit the event @@ -63,7 +69,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram address ipId, address, // parentIpId bytes calldata policyData - ) external override onlyLicensingModule returns (IPolicyFrameworkManager.VerifyLinkResponse memory) { + ) external override nonReentrant onlyLicensingModule returns (IPolicyFrameworkManager.VerifyLinkResponse memory) { UMLPolicy memory policy = abi.decode(policyData, (UMLPolicy)); IPolicyFrameworkManager.VerifyLinkResponse memory response = IPolicyFrameworkManager.VerifyLinkResponse({ isLinkingAllowed: true, // If you successfully mint and now hold a license, you have the right to link. @@ -83,15 +89,15 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram if (policy.derivativesApproval) { response.isLinkingAllowed = response.isLinkingAllowed && isDerivativeApproved(licenseId, ipId); } - - for (uint256 i = 0; i < policy.commercializers.length; i++) { - if (!policy.commercializers[i].supportsInterface(type(IHookModule).interfaceId)) { - revert Errors.PolicyFrameworkManager__CommercializerDoesNotSupportHook(policy.commercializers[i]); + if (policy.commercializerChecker != address(0)) { + if (!policy.commercializerChecker.supportsInterface(type(IHookModule).interfaceId)) { + revert Errors.PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook( + policy.commercializerChecker + ); } - if (!IHookModule(policy.commercializers[i]).verify(caller, policy.commercializersData[i])) { + if (!IHookModule(policy.commercializerChecker).verify(caller, policy.commercializerCheckerData)) { response.isLinkingAllowed = false; - break; } } @@ -108,7 +114,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram address, uint256, bytes memory policyData - ) external onlyLicensingModule returns (bool) { + ) external nonReentrant onlyLicensingModule returns (bool) { UMLPolicy memory policy = abi.decode(policyData, (UMLPolicy)); // If the policy defines no derivative is allowed, and policy was inherited, // we don't allow minting @@ -116,12 +122,14 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram return false; } - for (uint256 i = 0; i < policy.commercializers.length; i++) { - if (!policy.commercializers[i].supportsInterface(type(IHookModule).interfaceId)) { - revert Errors.PolicyFrameworkManager__CommercializerDoesNotSupportHook(policy.commercializers[i]); + if (policy.commercializerChecker != address(0)) { + if (!policy.commercializerChecker.supportsInterface(type(IHookModule).interfaceId)) { + revert Errors.PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook( + policy.commercializerChecker + ); } - if (!IHookModule(policy.commercializers[i]).verify(caller, policy.commercializersData[i])) { + if (!IHookModule(policy.commercializerChecker).verify(caller, policy.commercializerCheckerData)) { return false; } } @@ -246,7 +254,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram return (changedAgg, abi.encode(agg)); } - function policyToJson(bytes memory policyData) public view returns (string memory) { + function policyToJson(bytes memory policyData) public pure returns (string memory) { UMLPolicy memory policy = abi.decode(policyData, (UMLPolicy)); /* solhint-disable */ @@ -276,23 +284,20 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram '{"trait_type": "commercialRevShare", "value": ', Strings.toString(policy.commercialRevShare), "}," - '{"trait_type": "commercializers", "value": [' ) ); - - uint256 commercializerCount = policy.commercializers.length; - for (uint256 i = 0; i < commercializerCount; ++i) { - json = string(abi.encodePacked(json, '"', policy.commercializers[i].toHexString(), '"')); - if (i != commercializerCount - 1) { - json = string(abi.encodePacked(json, ",")); - } - } + json = string( + abi.encodePacked( + json, + '{"trait_type": "commercializerCheck", "value": "', + policy.commercializerChecker.toHexString() + ) + ); // TODO: add commercializersData? - json = string( abi.encodePacked( json, - ']}, {"trait_type": "derivativesAllowed", "value": "', + '"}, {"trait_type": "derivativesAllowed", "value": "', policy.derivativesAllowed ? "true" : "false", '"},', '{"trait_type": "derivativesAttribution", "value": "', @@ -343,7 +348,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram if (policy.commercialAttribution) { revert UMLFrameworkErrors.UMLPolicyFrameworkManager__CommecialDisabled_CantAddAttribution(); } - if (policy.commercializers.length > 0) { + if (policy.commercializerChecker != address(0)) { revert UMLFrameworkErrors.UMLPolicyFrameworkManager__CommercialDisabled_CantAddCommercializers(); } if (policy.commercialRevShare > 0) { @@ -360,8 +365,13 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram if (policy.royaltyPolicy == address(0)) { revert UMLFrameworkErrors.UMLPolicyFrameworkManager__CommecialEnabled_RoyaltyPolicyRequired(); } - if (policy.commercializers.length != policy.commercializersData.length) { - revert UMLFrameworkErrors.UMLPolicyFrameworkManager__CommercializersDataMismatch(); + if (policy.commercializerChecker != address(0)) { + if (!policy.commercializerChecker.supportsInterface(type(IHookModule).interfaceId)) { + revert Errors.PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook( + policy.commercializerChecker + ); + } + IHookModule(policy.commercializerChecker).validateConfig(policy.commercializerCheckerData); } } } @@ -395,7 +405,7 @@ contract UMLPolicyFrameworkManager is IUMLPolicyFrameworkManager, BasePolicyFram bytes32 oldHash, bytes32 newHash, bytes32 permissive - ) internal view returns (bytes32 result) { + ) internal pure returns (bytes32 result) { if (oldHash == newHash) { return newHash; } diff --git a/script/foundry/deployment/Main.s.sol b/script/foundry/deployment/Main.s.sol index f4d66c734..60bc9b52f 100644 --- a/script/foundry/deployment/Main.s.sol +++ b/script/foundry/deployment/Main.s.sol @@ -381,8 +381,8 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler { transferable: true, commercialUse: true, commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 100, derivativesAllowed: true, derivativesAttribution: false, @@ -402,8 +402,8 @@ contract Main is Script, BroadcastManager, JsonDeploymentHandler { transferable: false, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: true, diff --git a/test/foundry/ModuleRegistry.t.sol b/test/foundry/ModuleRegistry.t.sol index 281caad63..28bbcbab1 100644 --- a/test/foundry/ModuleRegistry.t.sol +++ b/test/foundry/ModuleRegistry.t.sol @@ -17,7 +17,7 @@ import { Governance } from "contracts/governance/Governance.sol"; import { MODULE_TYPE_DEFAULT, MODULE_TYPE_HOOK } from "contracts/lib/modules/Module.sol"; import { IModule } from "contracts/interfaces/modules/base/IModule.sol"; import { IHookModule } from "../../contracts/interfaces/modules/base/IHookModule.sol"; -import { TokenGatedHook } from "../../contracts/modules/hooks/TokenGatedHook.sol"; +import { MockTokenGatedHook } from "test/foundry/mocks/MockTokenGatedHook.sol"; contract ModuleRegistryTest is Test { IPAccountRegistry public registry; @@ -27,7 +27,7 @@ contract ModuleRegistryTest is Test { MockAccessController public accessController = new MockAccessController(); MockModule public module; CustomModule public customModule; - TokenGatedHook public tokenGatedHook; + MockTokenGatedHook public tokenGatedHook; Governance public governance; function setUp() public { @@ -37,7 +37,7 @@ contract ModuleRegistryTest is Test { registry = new IPAccountRegistry(address(erc6551Registry), address(accessController), address(implementation)); module = new MockModule(address(registry), address(moduleRegistry), "MockModule"); customModule = new CustomModule(); - tokenGatedHook = new TokenGatedHook(); + tokenGatedHook = new MockTokenGatedHook(); } function test_ModuleRegistry_registerModule() public { @@ -147,8 +147,8 @@ contract ModuleRegistryTest is Test { function test_ModuleRegistry_registerModuleWithHookModuleType() public { moduleRegistry.registerModuleType(MODULE_TYPE_HOOK, type(IHookModule).interfaceId); - moduleRegistry.registerModule("TokenGatedHook", address(tokenGatedHook), MODULE_TYPE_HOOK); - assertEq(moduleRegistry.getModule("TokenGatedHook"), address(tokenGatedHook)); + moduleRegistry.registerModule("MockTokenGatedHook", address(tokenGatedHook), MODULE_TYPE_HOOK); + assertEq(moduleRegistry.getModule("MockTokenGatedHook"), address(tokenGatedHook)); assertTrue(moduleRegistry.isRegistered(address(tokenGatedHook))); assertEq(moduleRegistry.getModuleType(address(tokenGatedHook)), MODULE_TYPE_HOOK); } diff --git a/test/foundry/integration/big-bang/NftLicenseRoyalty.t.sol b/test/foundry/integration/big-bang/NftLicenseRoyalty.t.sol index c97b1f57f..50d308c33 100644 --- a/test/foundry/integration/big-bang/NftLicenseRoyalty.t.sol +++ b/test/foundry/integration/big-bang/NftLicenseRoyalty.t.sol @@ -64,8 +64,8 @@ contract BigBang_Integration_NftLicenseRoyalty is BaseIntegration, Integration_S }), UMLPolicyCommercialParams({ commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: minRevShare, royaltyPolicy: address(royaltyPolicyLS) }), diff --git a/test/foundry/integration/big-bang/SingleNftCollection.t.sol b/test/foundry/integration/big-bang/SingleNftCollection.t.sol index bb119b3d1..e989d3f83 100644 --- a/test/foundry/integration/big-bang/SingleNftCollection.t.sol +++ b/test/foundry/integration/big-bang/SingleNftCollection.t.sol @@ -53,8 +53,8 @@ contract BigBang_Integration_SingleNftCollection is BaseIntegration, Integration }), UMLPolicyCommercialParams({ commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 10, royaltyPolicy: address(royaltyPolicyLS) }), diff --git a/test/foundry/integration/shared/LicenseHelper.sol b/test/foundry/integration/shared/LicenseHelper.sol index 78d132a0f..954f89ba6 100644 --- a/test/foundry/integration/shared/LicenseHelper.sol +++ b/test/foundry/integration/shared/LicenseHelper.sol @@ -41,8 +41,8 @@ struct UMLPolicyGenericParams { struct UMLPolicyCommercialParams { bool commercialAttribution; - address[] commercializers; - bytes[] commercializersData; + address commercializerChecker; + bytes commercializerCheckerData; uint32 commercialRevShare; address royaltyPolicy; } @@ -166,8 +166,8 @@ contract Integration_Shared_LicensingHelper { attribution: gparams.attribution, commercialUse: true, commercialAttribution: cparams.commercialAttribution, - commercializers: cparams.commercializers, - commercializersData: cparams.commercializersData, + commercializerChecker: cparams.commercializerChecker, + commercializerCheckerData: cparams.commercializerCheckerData, commercialRevShare: cparams.commercialRevShare, derivativesAllowed: true, derivativesAttribution: dparams.derivativesAttribution, @@ -196,8 +196,8 @@ contract Integration_Shared_LicensingHelper { attribution: gparams.attribution, commercialUse: true, commercialAttribution: cparams.commercialAttribution, - commercializers: cparams.commercializers, - commercializersData: cparams.commercializersData, + commercializerChecker: cparams.commercializerChecker, + commercializerCheckerData: cparams.commercializerCheckerData, commercialRevShare: cparams.commercialRevShare, derivativesAllowed: false, derivativesAttribution: false, @@ -226,8 +226,8 @@ contract Integration_Shared_LicensingHelper { attribution: gparams.attribution, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: dparams.derivativesAttribution, @@ -253,8 +253,8 @@ contract Integration_Shared_LicensingHelper { attribution: gparams.attribution, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: false, derivativesAttribution: false, diff --git a/contracts/modules/hooks/TokenGatedHook.sol b/test/foundry/mocks/MockTokenGatedHook.sol similarity index 62% rename from contracts/modules/hooks/TokenGatedHook.sol rename to test/foundry/mocks/MockTokenGatedHook.sol index b1b23b5df..9607887bd 100644 --- a/contracts/modules/hooks/TokenGatedHook.sol +++ b/test/foundry/mocks/MockTokenGatedHook.sol @@ -4,14 +4,15 @@ pragma solidity ^0.8.23; import { IERC165, ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import { IHookModule } from "../../interfaces/modules/base/IHookModule.sol"; +import { IHookModule } from "../../../contracts/interfaces/modules/base/IHookModule.sol"; +import { BaseModule } from "../../../contracts/modules/BaseModule.sol"; /// @title Token Gated Hook. /// @notice Hook for ensursing caller is the owner of an NFT token. -contract TokenGatedHook is ERC165, IHookModule { +contract MockTokenGatedHook is BaseModule, IHookModule { using ERC165Checker for address; - string public constant override name = "TokenGatedHook"; + string public constant override name = "MockTokenGatedHook"; function verify(address caller, bytes calldata data) external view returns (bool) { address tokenAddress = abi.decode(data, (address)); @@ -24,7 +25,13 @@ contract TokenGatedHook is ERC165, IHookModule { return IERC721(tokenAddress).balanceOf(caller) > 0; } - function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + function validateConfig(bytes calldata configData) external view override { + address tokenAddress = abi.decode(configData, (address)); + require(tokenAddress.supportsInterface(type(IERC721).interfaceId), "MockTokenGatedHook: Invalid token address"); + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(BaseModule, IERC165) returns (bool) { return interfaceId == type(IHookModule).interfaceId || super.supportsInterface(interfaceId); } + } diff --git a/test/foundry/mocks/licensing/MintPaymentPolicyFrameworkManager.sol b/test/foundry/mocks/licensing/MintPaymentPolicyFrameworkManager.sol index 30c5811a1..d6a29e583 100644 --- a/test/foundry/mocks/licensing/MintPaymentPolicyFrameworkManager.sol +++ b/test/foundry/mocks/licensing/MintPaymentPolicyFrameworkManager.sol @@ -87,7 +87,7 @@ contract MintPaymentPolicyFrameworkManager is BasePolicyFrameworkManager { address, // to uint256, // amount bytes memory // policyData - ) external returns (bool) { + ) external pure returns (bool) { return true; } diff --git a/test/foundry/mocks/licensing/MockPolicyFrameworkManager.sol b/test/foundry/mocks/licensing/MockPolicyFrameworkManager.sol index 600b0ca76..01f0e2025 100644 --- a/test/foundry/mocks/licensing/MockPolicyFrameworkManager.sol +++ b/test/foundry/mocks/licensing/MockPolicyFrameworkManager.sol @@ -80,7 +80,7 @@ contract MockPolicyFrameworkManager is BasePolicyFrameworkManager { return 0; } - function isPolicyCommercial(uint256 policyId) external view returns (bool) { + function isPolicyCommercial(uint256 policyId) external pure returns (bool) { return policyId % 2 == 0; } } diff --git a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol index 79ce8d779..9c0d66a9f 100644 --- a/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol +++ b/test/foundry/modules/dispute/ArbitrationPolicySP.t.sol @@ -50,8 +50,8 @@ contract TestArbitrationPolicySP is TestHelper { }), UMLPolicyCommercialParams({ commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 10, royaltyPolicy: address(royaltyPolicyLS) }), diff --git a/test/foundry/modules/dispute/DisputeModule.t.sol b/test/foundry/modules/dispute/DisputeModule.t.sol index ebcb83aa0..d12bc73cb 100644 --- a/test/foundry/modules/dispute/DisputeModule.t.sol +++ b/test/foundry/modules/dispute/DisputeModule.t.sol @@ -70,8 +70,8 @@ contract TestDisputeModule is TestHelper { }), UMLPolicyCommercialParams({ commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 10, royaltyPolicy: address(royaltyPolicyLS) }), diff --git a/test/foundry/modules/hooks/TokenGatedHook.t.sol b/test/foundry/modules/hooks/TokenGatedHook.t.sol deleted file mode 100644 index 42f556651..000000000 --- a/test/foundry/modules/hooks/TokenGatedHook.t.sol +++ /dev/null @@ -1,52 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import { Test } from "forge-std/Test.sol"; -import { TokenGatedHook } from "contracts/modules/hooks/TokenGatedHook.sol"; -import { MockERC721 } from "test/foundry/mocks/MockERC721.sol"; - -contract TokenGatedHookTest is Test { - TokenGatedHook public tokenGatedHook; - MockERC721 nft = new MockERC721("MockERC721"); - address goodCaller = vm.addr(1); - address badCaller = vm.addr(2); - - function setUp() public { - tokenGatedHook = new TokenGatedHook(); - nft.mint(goodCaller); - } - - function test_TokenGatedHook_CallerHasNFT() public { - bytes memory data = abi.encode(address(nft)); - assertEq(tokenGatedHook.verify(goodCaller, data), true); - } - - function test_TokenGatedHook_CallerDoesNotHaveNFT() public { - bytes memory data = abi.encode(address(nft)); - assertEq(tokenGatedHook.verify(badCaller, data), false); - } - - function test_TokenGatedHook_CallerHasNftTwice() public { - bytes memory data = abi.encode(address(nft)); - assertEq(tokenGatedHook.verify(goodCaller, data), true); - assertEq(tokenGatedHook.verify(goodCaller, data), true); - } - - function test_TokenGatedHook_CallerHasNftThenBurnsIt() public { - bytes memory data = abi.encode(address(nft)); - assertEq(tokenGatedHook.verify(goodCaller, data), true); - vm.prank(goodCaller); - nft.burn(1); - assertEq(tokenGatedHook.verify(goodCaller, data), false); - } - - function test_TokenGatedHook_CallerIsZeroAddress() public { - bytes memory data = abi.encode(address(nft)); - assertEq(tokenGatedHook.verify(address(0), data), false); - } - - function test_TokenGatedHook_InvalidNftCollectionAddress() public { - bytes memory data = abi.encode(address(0x2222)); - assertEq(tokenGatedHook.verify(goodCaller, data), false); - } -} diff --git a/test/foundry/modules/licensing/LicensingModule.t.sol b/test/foundry/modules/licensing/LicensingModule.t.sol index cf68bd87b..5e7cb5dc5 100644 --- a/test/foundry/modules/licensing/LicensingModule.t.sol +++ b/test/foundry/modules/licensing/LicensingModule.t.sol @@ -19,7 +19,7 @@ import { LicenseRegistry } from "contracts/registries/LicenseRegistry.sol"; import { LicensingModule } from "contracts/modules/licensing/LicensingModule.sol"; import { RoyaltyModule } from "contracts/modules/royalty-module/RoyaltyModule.sol"; import { IPAssetRegistry } from "contracts/registries/IPAssetRegistry.sol"; -import { TokenGatedHook } from "contracts/modules/hooks/TokenGatedHook.sol"; +import { MockTokenGatedHook } from "test/foundry/mocks/MockTokenGatedHook.sol"; import { IPResolver } from "contracts/resolvers/IPResolver.sol"; import { RegistrationModule } from "contracts/modules/RegistrationModule.sol"; @@ -441,8 +441,8 @@ contract LicensingModuleTest is Test { attribution: true, commercialUse: true, commercialAttribution: true, - commercializers: new address[](2), - commercializersData: new bytes[](2), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: true, @@ -456,13 +456,10 @@ contract LicensingModuleTest is Test { }); gatedNftFoo.mintId(address(this), 1); - gatedNftBar.mintId(address(this), 1); - TokenGatedHook tokenGatedHook = new TokenGatedHook(); - policyData.commercializers[0] = address(tokenGatedHook); - policyData.commercializersData[0] = abi.encode(address(gatedNftFoo)); - policyData.commercializers[1] = address(tokenGatedHook); - policyData.commercializersData[1] = abi.encode(address(gatedNftBar)); + MockTokenGatedHook tokenGatedHook = new MockTokenGatedHook(); + policyData.commercializerChecker = address(tokenGatedHook); + policyData.commercializerCheckerData = abi.encode(address(gatedNftFoo)); policyData.territories[0] = "territory1"; policyData.distributionChannels[0] = "distributionChannel1"; @@ -551,7 +548,7 @@ contract LicensingModuleTest is Test { /* solhint-disable */ string - memory expectedJson = "eyJuYW1lIjogIlN0b3J5IFByb3RvY29sIExpY2Vuc2UgTkZUIiwgImRlc2NyaXB0aW9uIjogIkxpY2Vuc2UgYWdyZWVtZW50IHN0YXRpbmcgdGhlIHRlcm1zIG9mIGEgU3RvcnkgUHJvdG9jb2wgSVBBc3NldCIsICJhdHRyaWJ1dGVzIjogW3sidHJhaXRfdHlwZSI6ICJBdHRyaWJ1dGlvbiIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogIlRyYW5zZmVyYWJsZSIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogIkNvbW1lcmljYWwgVXNlIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiY29tbWVyY2lhbEF0dHJpYnV0aW9uIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiY29tbWVyY2lhbFJldlNoYXJlIiwgInZhbHVlIjogMH0seyJ0cmFpdF90eXBlIjogImNvbW1lcmNpYWxpemVycyIsICJ2YWx1ZSI6IFsiMHhhMDViYzBlYTdhMzZiY2FkODQxNjc0OWFmOGE2MzBhODkxZTJkNDZjIiwiMHhhMDViYzBlYTdhMzZiY2FkODQxNjc0OWFmOGE2MzBhODkxZTJkNDZjIl19LCB7InRyYWl0X3R5cGUiOiAiZGVyaXZhdGl2ZXNBbGxvd2VkIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiZGVyaXZhdGl2ZXNBdHRyaWJ1dGlvbiIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogImRlcml2YXRpdmVzQXBwcm92YWwiLCAidmFsdWUiOiAidHJ1ZSJ9LHsidHJhaXRfdHlwZSI6ICJkZXJpdmF0aXZlc1JlY2lwcm9jYWwiLCAidmFsdWUiOiAidHJ1ZSJ9LHsidHJhaXRfdHlwZSI6ICJkZXJpdmF0aXZlc1JldlNoYXJlIiwgInZhbHVlIjogMH0seyJ0cmFpdF90eXBlIjogInRlcnJpdG9yaWVzIiwgInZhbHVlIjogWyJ0ZXJyaXRvcnkxIl19LCB7InRyYWl0X3R5cGUiOiAiZGlzdHJpYnV0aW9uQ2hhbm5lbHMiLCAidmFsdWUiOiBbImRpc3RyaWJ1dGlvbkNoYW5uZWwxIl19XX0="; + memory expectedJson = "eyJuYW1lIjogIlN0b3J5IFByb3RvY29sIExpY2Vuc2UgTkZUIiwgImRlc2NyaXB0aW9uIjogIkxpY2Vuc2UgYWdyZWVtZW50IHN0YXRpbmcgdGhlIHRlcm1zIG9mIGEgU3RvcnkgUHJvdG9jb2wgSVBBc3NldCIsICJhdHRyaWJ1dGVzIjogW3sidHJhaXRfdHlwZSI6ICJBdHRyaWJ1dGlvbiIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogIlRyYW5zZmVyYWJsZSIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogIkNvbW1lcmljYWwgVXNlIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiY29tbWVyY2lhbEF0dHJpYnV0aW9uIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiY29tbWVyY2lhbFJldlNoYXJlIiwgInZhbHVlIjogMH0seyJ0cmFpdF90eXBlIjogImNvbW1lcmNpYWxpemVyQ2hlY2siLCAidmFsdWUiOiAiMHhhMDViYzBlYTdhMzZiY2FkODQxNjc0OWFmOGE2MzBhODkxZTJkNDZjIn0sIHsidHJhaXRfdHlwZSI6ICJkZXJpdmF0aXZlc0FsbG93ZWQiLCAidmFsdWUiOiAidHJ1ZSJ9LHsidHJhaXRfdHlwZSI6ICJkZXJpdmF0aXZlc0F0dHJpYnV0aW9uIiwgInZhbHVlIjogInRydWUifSx7InRyYWl0X3R5cGUiOiAiZGVyaXZhdGl2ZXNBcHByb3ZhbCIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogImRlcml2YXRpdmVzUmVjaXByb2NhbCIsICJ2YWx1ZSI6ICJ0cnVlIn0seyJ0cmFpdF90eXBlIjogImRlcml2YXRpdmVzUmV2U2hhcmUiLCAidmFsdWUiOiAwfSx7InRyYWl0X3R5cGUiOiAidGVycml0b3JpZXMiLCAidmFsdWUiOiBbInRlcnJpdG9yeTEiXX0sIHsidHJhaXRfdHlwZSI6ICJkaXN0cmlidXRpb25DaGFubmVscyIsICJ2YWx1ZSI6IFsiZGlzdHJpYnV0aW9uQ2hhbm5lbDEiXX1dfQ=="; /* solhint-enable */ string memory expectedUri = string(abi.encodePacked("data:application/json;base64,", expectedJson)); @@ -567,8 +564,8 @@ contract LicensingModuleTest is Test { attribution: true, commercialUse: true, commercialAttribution: true, - commercializers: new address[](2), - commercializersData: new bytes[](2), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: true, @@ -583,11 +580,10 @@ contract LicensingModuleTest is Test { gatedNftFoo.mintId(address(this), 1); - TokenGatedHook tokenGatedHook = new TokenGatedHook(); - policyData.commercializers[0] = address(tokenGatedHook); - policyData.commercializersData[0] = abi.encode(address(gatedNftFoo)); - policyData.commercializers[1] = address(tokenGatedHook); - policyData.commercializersData[1] = abi.encode(address(gatedNftBar)); + MockTokenGatedHook tokenGatedHook = new MockTokenGatedHook(); + policyData.commercializerChecker = address(tokenGatedHook); + // address(this) doesn't hold token of NFT collection gatedNftBar, so the verification will fail + policyData.commercializerCheckerData = abi.encode(address(gatedNftBar)); policyData.territories[0] = "territory1"; policyData.distributionChannels[0] = "distributionChannel1"; diff --git a/test/foundry/modules/licensing/UMLPolicyFramework.t.sol b/test/foundry/modules/licensing/UMLPolicyFramework.t.sol index 7afba477e..e21d25449 100644 --- a/test/foundry/modules/licensing/UMLPolicyFramework.t.sol +++ b/test/foundry/modules/licensing/UMLPolicyFramework.t.sol @@ -7,7 +7,7 @@ import { UMLPolicy } from "contracts/interfaces/modules/licensing/IUMLPolicyFram import { UMLPolicyFrameworkManager } from "contracts/modules/licensing/UMLPolicyFrameworkManager.sol"; import { TestHelper } from "test/foundry/utils/TestHelper.sol"; import { MockERC721 } from "test/foundry/mocks/MockERC721.sol"; -import { TokenGatedHook } from "contracts/modules/hooks/TokenGatedHook.sol"; +import { MockTokenGatedHook } from "test/foundry/mocks/MockTokenGatedHook.sol"; contract UMLPolicyFrameworkTest is TestHelper { UMLPolicyFrameworkManager internal umlFramework; @@ -18,6 +18,7 @@ contract UMLPolicyFrameworkTest is TestHelper { address public ipOwner = vm.addr(1); address public licenseHolder = address(0x101); MockERC721 internal gatedNftFoo = new MockERC721("GatedNftFoo"); + MockTokenGatedHook internal tokenGatedHook = new MockTokenGatedHook(); function setUp() public override { TestHelper.setUp(); @@ -73,8 +74,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: false, commercialUse: true, commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: "", commercialRevShare: 0, derivativesAllowed: false, // If false, derivativesRevShare should revert derivativesAttribution: false, @@ -102,8 +103,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: false, commercialUse: false, commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: false, derivativesAttribution: false, @@ -113,28 +114,25 @@ contract UMLPolicyFrameworkTest is TestHelper { territories: emptyStringArray, distributionChannels: emptyStringArray, contentRestrictions: emptyStringArray, - royaltyPolicy: address(0) // must be 0 because commercialUse = false + royaltyPolicy: zeroAddress // must be 0 because commercialUse = false }); gatedNftFoo.mintId(address(this), 1); - TokenGatedHook tokenGatedHook = new TokenGatedHook(); // commercialAttribution = true should revert vm.expectRevert(UMLFrameworkErrors.UMLPolicyFrameworkManager__CommecialDisabled_CantAddAttribution.selector); umlFramework.registerPolicy(umlPolicy); // Non empty commercializers should revert umlPolicy.commercialAttribution = false; - umlPolicy.commercializers = new address[](1); - umlPolicy.commercializers[0] = address(tokenGatedHook); - umlPolicy.commercializersData = new bytes[](1); - umlPolicy.commercializersData[0] = abi.encode(address(gatedNftFoo)); + umlPolicy.commercializerChecker = address(tokenGatedHook); + umlPolicy.commercializerCheckerData = abi.encode(address(gatedNftFoo)); vm.expectRevert( UMLFrameworkErrors.UMLPolicyFrameworkManager__CommercialDisabled_CantAddCommercializers.selector ); umlFramework.registerPolicy(umlPolicy); // No rev share should be set; revert - umlPolicy.commercializers = new address[](0); - umlPolicy.commercializersData = new bytes[](0); + umlPolicy.commercializerChecker = zeroAddress; + umlPolicy.commercializerCheckerData = emptyBytes; umlPolicy.commercialRevShare = 1; vm.expectRevert(UMLFrameworkErrors.UMLPolicyFrameworkManager__CommecialDisabled_CantAddRevShare.selector); umlFramework.registerPolicy(umlPolicy); @@ -146,19 +144,13 @@ contract UMLPolicyFrameworkTest is TestHelper { } function test_UMLPolicyFrameworkManager__commercialUse_valuesSetCorrectly() public { - address[] memory commercializers = new address[](2); - commercializers[0] = address(0x123); - commercializers[1] = address(0x456); - bytes[] memory commercializersData = new bytes[](2); - commercializersData[0] = abi.encode(address(0x987)); - commercializersData[1] = abi.encode(address(0x653)); UMLPolicy memory umlPolicy = UMLPolicy({ attribution: false, transferable: false, commercialUse: true, commercialAttribution: true, - commercializers: commercializers, - commercializersData: commercializersData, + commercializerChecker: address(tokenGatedHook), + commercializerCheckerData: abi.encode(address(gatedNftFoo)), commercialRevShare: 123123, derivativesAllowed: true, // If false, derivativesRevShare should revert derivativesAttribution: false, @@ -175,6 +167,41 @@ contract UMLPolicyFrameworkTest is TestHelper { assertEq(keccak256(abi.encode(policy)), keccak256(abi.encode(umlPolicy))); } + function test_UMLPolicyFrameworkManager__commercialUse_InvalidCommericalizer() public { + address invalidCommercializerChecker = address(0x123); + bytes memory invalideCommercializerCheckerData = abi.encode(address(0x456)); + UMLPolicy memory umlPolicy = UMLPolicy({ + attribution: false, + transferable: false, + commercialUse: true, + commercialAttribution: true, + commercializerChecker: invalidCommercializerChecker, + commercializerCheckerData: abi.encode(address(gatedNftFoo)), + commercialRevShare: 123123, + derivativesAllowed: true, // If false, derivativesRevShare should revert + derivativesAttribution: false, + derivativesApproval: false, + derivativesReciprocal: false, + derivativesRevShare: 1, + territories: emptyStringArray, + distributionChannels: emptyStringArray, + contentRestrictions: emptyStringArray, + royaltyPolicy: address(mockRoyaltyPolicyLS) + }); + vm.expectRevert( + abi.encodeWithSelector( + Errors.PolicyFrameworkManager__CommercializerCheckerDoesNotSupportHook.selector, + invalidCommercializerChecker + ) + ); + umlFramework.registerPolicy(umlPolicy); + + umlPolicy.commercializerChecker = address(tokenGatedHook); + umlPolicy.commercializerCheckerData = invalideCommercializerCheckerData; + vm.expectRevert("MockTokenGatedHook: Invalid token address"); + umlFramework.registerPolicy(umlPolicy); + } + function test_UMLPolicyFrameworkManager__derivatives_notAllowed_revert_settingIncompatibleTerms() public { // If no derivative values allowed UMLPolicy memory umlPolicy = UMLPolicy({ @@ -182,8 +209,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: false, commercialUse: true, // So derivativesRevShare doesn't revert for this commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: false, derivativesAttribution: true, @@ -221,8 +248,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: false, commercialUse: true, // If false, derivativesRevShare should revert commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: true, // If false, derivativesRevShare should revert derivativesAttribution: true, @@ -250,8 +277,8 @@ contract UMLPolicyFrameworkTest is TestHelper { attribution: false, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: false, @@ -261,7 +288,7 @@ contract UMLPolicyFrameworkTest is TestHelper { territories: emptyStringArray, distributionChannels: emptyStringArray, contentRestrictions: emptyStringArray, - royaltyPolicy: address(0) // must be 0 because commercialUse = false + royaltyPolicy: zeroAddress // must be 0 because commercialUse = false }) ); @@ -290,8 +317,8 @@ contract UMLPolicyFrameworkTest is TestHelper { attribution: false, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: true, derivativesAttribution: false, @@ -301,7 +328,7 @@ contract UMLPolicyFrameworkTest is TestHelper { territories: emptyStringArray, distributionChannels: emptyStringArray, contentRestrictions: emptyStringArray, - royaltyPolicy: address(0) // must be 0 because commercialUse = false + royaltyPolicy: zeroAddress // must be 0 because commercialUse = false }) ); @@ -313,7 +340,7 @@ contract UMLPolicyFrameworkTest is TestHelper { vm.expectRevert(Errors.LicenseRegistry__NotTransferable.selector); vm.prank(ipOwner); - licenseRegistry.safeTransferFrom(ipOwner, licenseHolder, licenseId, 1, ""); + licenseRegistry.safeTransferFrom(ipOwner, licenseHolder, licenseId, 1, emptyBytes); vm.prank(licenseRegistry.licensorIpId(licenseId)); umlFramework.setApproval(licenseId, ipId2, true); @@ -337,8 +364,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: true, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: false, // If false, derivativesRevShare should revert derivativesAttribution: false, @@ -348,7 +375,7 @@ contract UMLPolicyFrameworkTest is TestHelper { territories: emptyStringArray, distributionChannels: emptyStringArray, contentRestrictions: emptyStringArray, - royaltyPolicy: address(0) // must be 0 because commercialUse = false + royaltyPolicy: zeroAddress // must be 0 because commercialUse = false }); uint256 policyId = umlFramework.registerPolicy(umlPolicy); vm.prank(ipOwner); @@ -357,7 +384,7 @@ contract UMLPolicyFrameworkTest is TestHelper { assertEq(licenseRegistry.balanceOf(licenseHolder, licenseId), 1); address licenseHolder2 = address(0x222); vm.prank(licenseHolder); - licenseRegistry.safeTransferFrom(licenseHolder, licenseHolder2, licenseId, 1, ""); + licenseRegistry.safeTransferFrom(licenseHolder, licenseHolder2, licenseId, 1, emptyBytes); assertEq(licenseRegistry.balanceOf(licenseHolder, licenseId), 0); assertEq(licenseRegistry.balanceOf(licenseHolder2, licenseId), 1); } @@ -368,8 +395,8 @@ contract UMLPolicyFrameworkTest is TestHelper { transferable: false, commercialUse: false, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: zeroAddress, + commercializerCheckerData: emptyBytes, commercialRevShare: 0, derivativesAllowed: false, // If false, derivativesRevShare should revert derivativesAttribution: false, @@ -379,7 +406,7 @@ contract UMLPolicyFrameworkTest is TestHelper { territories: emptyStringArray, distributionChannels: emptyStringArray, contentRestrictions: emptyStringArray, - royaltyPolicy: address(0) // must be 0 because commercialUse = false + royaltyPolicy: zeroAddress // must be 0 because commercialUse = false }); uint256 policyId = umlFramework.registerPolicy(umlPolicy); vm.prank(ipOwner); @@ -389,7 +416,7 @@ contract UMLPolicyFrameworkTest is TestHelper { address licenseHolder2 = address(0x222); vm.startPrank(licenseHolder); vm.expectRevert(Errors.LicenseRegistry__NotTransferable.selector); - licenseRegistry.safeTransferFrom(licenseHolder, licenseHolder2, licenseId, 1, ""); + licenseRegistry.safeTransferFrom(licenseHolder, licenseHolder2, licenseId, 1, emptyBytes); vm.stopPrank(); } diff --git a/test/foundry/modules/royalty/LSClaimer.t.sol b/test/foundry/modules/royalty/LSClaimer.t.sol index 107773138..a81a79d5f 100644 --- a/test/foundry/modules/royalty/LSClaimer.t.sol +++ b/test/foundry/modules/royalty/LSClaimer.t.sol @@ -48,8 +48,8 @@ contract TestLSClaimer is TestHelper { }), UMLPolicyCommercialParams({ commercialAttribution: true, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: 10, royaltyPolicy: address(royaltyPolicyLS) }), diff --git a/test/foundry/utils/TestHelper.sol b/test/foundry/utils/TestHelper.sol index 3c9d98f62..81fe8d32f 100644 --- a/test/foundry/utils/TestHelper.sol +++ b/test/foundry/utils/TestHelper.sol @@ -45,6 +45,9 @@ contract TestHelper is Test, DeployHelper { mapping(string => UMLPolicy) internal policies; string[] internal emptyStringArray = new string[](0); + address internal zeroAddress = address(0); + string internal emptyString = ""; + bytes internal emptyBytes = ""; function setUp() public virtual { // solhint-disable no-console @@ -92,8 +95,8 @@ contract TestHelper is Test, DeployHelper { attribution: gparams.attribution, commercialUse: commercialUse, commercialAttribution: cparams.commercialAttribution, - commercializers: cparams.commercializers, - commercializersData: cparams.commercializersData, + commercializerChecker: cparams.commercializerChecker, + commercializerCheckerData: cparams.commercializerCheckerData, commercialRevShare: cparams.commercialRevShare, derivativesAllowed: derivativesAllowed, derivativesAttribution: dparams.derivativesAttribution, @@ -122,8 +125,8 @@ contract TestHelper is Test, DeployHelper { attribution: true, commercialUse: commercial, commercialAttribution: false, - commercializers: new address[](0), - commercializersData: new bytes[](0), + commercializerChecker: address(0), + commercializerCheckerData: "", commercialRevShare: commercial ? commercialRevShare : 0, derivativesAllowed: derivatives, derivativesAttribution: false,