diff --git a/contracts/interfaces/modules/licensing/ILicensingModule.sol b/contracts/interfaces/modules/licensing/ILicensingModule.sol index 2d31f284..b7a70b25 100644 --- a/contracts/interfaces/modules/licensing/ILicensingModule.sol +++ b/contracts/interfaces/modules/licensing/ILicensingModule.sol @@ -37,7 +37,9 @@ interface ILicensingModule is IModule { address indexed policyFrameworkManager, bytes frameworkData, address royaltyPolicy, - bytes royaltyData + bytes royaltyData, + uint256 mintingFee, + address mintingFeeToken ); /// @notice Emitted when a policy is added to an IP @@ -73,18 +75,9 @@ interface ILicensingModule is IModule { /// @param manager the address of the manager. Will be ERC165 checked for IPolicyFrameworkManager function registerPolicyFrameworkManager(address manager) external; - /// @notice Registers a policy into the contract. MUST be called by a registered framework or it will revert. - /// The policy data and its integrity must be verified by the policy framework manager. - /// @param isLicenseTransferable True if the license is transferable - /// @param royaltyPolicy The address of the royalty policy - /// @param royaltyData The royalty policy specific encoded data - /// @param frameworkData The policy framework specific encoded data - function registerPolicy( - bool isLicenseTransferable, - address royaltyPolicy, - bytes memory royaltyData, - bytes memory frameworkData - ) external returns (uint256 policyId); + /// @param pol The Licensing policy data. MUST have same policy framework as the caller address + /// @return policyId The id of the newly registered policy + function registerPolicy(Licensing.Policy memory pol) external returns (uint256 policyId); /// @notice Adds a policy to the set of policies of an IP /// @param ipId The id of the IP diff --git a/contracts/lib/Licensing.sol b/contracts/lib/Licensing.sol index fc4a0fb4..47e44cf6 100644 --- a/contracts/lib/Licensing.sol +++ b/contracts/lib/Licensing.sol @@ -11,12 +11,16 @@ library Licensing { /// @param frameworkData Data to be used by the policy framework to verify minting and linking /// @param royaltyPolicy address of the royalty policy to be used by the policy framework, if any /// @param royaltyData Data to be used by the royalty policy (for example, encoding of the royalty percentage) + /// @param mintingFee Fee to be paid when minting a license + /// @param mintingFeeToken Token to be used to pay the minting fee struct Policy { bool isLicenseTransferable; address policyFramework; bytes frameworkData; address royaltyPolicy; bytes royaltyData; + uint256 mintingFee; + address mintingFeeToken; } /// @notice Data that define a License Agreement NFT /// @param policyId Id of the policy this license is based on, which will be set in the derivative IP when the diff --git a/contracts/modules/licensing/LicensingModule.sol b/contracts/modules/licensing/LicensingModule.sol index cbc1b7ee..5fae07d1 100644 --- a/contracts/modules/licensing/LicensingModule.sol +++ b/contracts/modules/licensing/LicensingModule.sol @@ -113,35 +113,36 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen /// @notice Registers a policy into the contract. MUST be called by a registered framework or it will revert. /// The policy data and its integrity must be verified by the policy framework manager. - /// @param isLicenseTransferable True if the license is transferable - /// @param royaltyPolicy The address of the royalty policy - /// @param royaltyData The royalty policy specific encoded data - /// @param frameworkData The policy framework specific encoded data - function registerPolicy( - bool isLicenseTransferable, - address royaltyPolicy, - bytes memory royaltyData, - bytes memory frameworkData - ) external returns (uint256 policyId) { + /// @param pol The Licensing policy data. MUST have same policy framework as the caller address + /// @return policyId The id of the newly registered policy + function registerPolicy(Licensing.Policy memory pol) external returns (uint256 policyId) { _verifyRegisteredFramework(address(msg.sender)); - Licensing.Policy memory pol = Licensing.Policy({ - isLicenseTransferable: isLicenseTransferable, - policyFramework: msg.sender, - frameworkData: frameworkData, - royaltyPolicy: royaltyPolicy, - royaltyData: royaltyData - }); - + if (pol.policyFramework != address(msg.sender)) { + revert Errors.LicensingModule__RegisterPolicyFrameworkMismatch(); + } + if (pol.royaltyPolicy != address(0) && !ROYALTY_MODULE.isWhitelistedRoyaltyPolicy(pol.royaltyPolicy)) { + revert Errors.LicensingModule__RoyaltyPolicyNotWhitelisted(); + } + if (pol.mintingFee > 0 && !ROYALTY_MODULE.isWhitelistedRoyaltyToken(pol.mintingFeeToken)) { + revert Errors.LicensingModule__MintingFeeTokenNotWhitelisted(); + } (uint256 polId, bool newPol) = DataUniqueness.addIdOrGetExisting( abi.encode(pol), _hashedPolicies, _totalPolicies ); - if (newPol) { _totalPolicies = polId; _policies[polId] = pol; - emit PolicyRegistered(polId, msg.sender, frameworkData, royaltyPolicy, royaltyData); + emit PolicyRegistered( + polId, + pol.policyFramework, + pol.frameworkData, + pol.royaltyPolicy, + pol.royaltyData, + pol.mintingFee, + pol.mintingFeeToken + ); } return polId; } @@ -204,7 +205,10 @@ contract LicensingModule is AccessControlled, ILicensingModule, BaseModule, Reen // If the policy has a royalty policy, we need to call the royalty module to process the minting // Otherwise, it's non commercial and we can skip the call. if (pol.royaltyPolicy != address(0)) { - ROYALTY_MODULE.onLicenseMinting(licensorIpId, pol.royaltyPolicy, pol.royaltyData, royaltyContext); + // If there's a minting fee, sender must pay it + if (pol.mintingFee > 0) { + ROYALTY_MODULE.payLicenseMintingFee(licensorIpId, msg.sender, pol.royaltyPolicy, pol.mintingFeeToken, pol.mintingFee); + } } // If a policy is set, then is only up to the policy params.