Skip to content

Commit

Permalink
Allow IP Owner to Customize and Override Royalty Percentage in Licens…
Browse files Browse the repository at this point in the history
…e Terms (#269)
  • Loading branch information
kingster-will authored Oct 17, 2024
1 parent 7d536c7 commit a50c930
Show file tree
Hide file tree
Showing 10 changed files with 237 additions and 22 deletions.
7 changes: 7 additions & 0 deletions contracts/interfaces/modules/licensing/ILicenseTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,11 @@ interface ILicenseTemplate is IERC165 {
uint256[] calldata licenseTermsIds,
address childIpOwner
) external returns (bool);

/// @notice Verifies if the royalty percentage defined in the licenseTermsId can be overridden with
/// the given newRoyaltyPercent.
/// @param licenseTermsId The ID of the license terms.
/// @param newRoyaltyPercent The new royalty percentage.
/// @return True if the royalty percentage can be overridden, false otherwise.
function canOverrideRoyaltyPercent(uint256 licenseTermsId, uint32 newRoyaltyPercent) external view returns (bool);
}
3 changes: 2 additions & 1 deletion contracts/interfaces/registries/ILicenseRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ interface ILicenseRegistry {
event LicensingConfigSetForLicense(
address indexed ipId,
address indexed licenseTemplate,
uint256 indexed licenseTermsId
uint256 indexed licenseTermsId,
Licensing.LicensingConfig licensingConfig
);

/// @notice Emitted when set new default license terms.
Expand Down
9 changes: 9 additions & 0 deletions contracts/lib/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,15 @@ library Errors {
/// @notice Zero address provided for IP Graph ACL.
error LicenseRegistry__ZeroIPGraphACL();

/// @notice When Set LicenseConfig the license template cannot be Zero address if royalty percentage is not Zero.
error LicensingModule__LicenseTemplateCannotBeZeroAddressToOverrideRoyaltyPercent();

/// @notice Current License does not allow to override royalty percentage.
error LicensingModule__CurrentLicenseNotAllowOverrideRoyaltyPercent(
address licenseTemplate,
uint256 licenseTermsId,
uint32 newRoyaltyPercent
);
////////////////////////////////////////////////////////////////////////////
// License Token //
////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions contracts/lib/Licensing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ library Licensing {
/// @param mintingFee The minting fee to be paid when minting license tokens.
/// @param licensingHook The hook contract address for the licensing module, or address(0) if none
/// @param hookData The data to be used by the licensing hook.
/// @param commercialRevShare The commercial revenue share percentage.
struct LicensingConfig {
bool isSet;
uint256 mintingFee;
address licensingHook;
bytes hookData;
uint32 commercialRevShare;
}
}
31 changes: 30 additions & 1 deletion contracts/modules/licensing/LicensingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,14 @@ contract LicensingModule is
uint32[] memory rPercents = new uint32[](parentIpIds.length);
for (uint256 i = 0; i < parentIpIds.length; i++) {
(address royaltyPolicy, uint32 royaltyPercent, , ) = lct.getRoyaltyPolicy(licenseTermsIds[i]);
Licensing.LicensingConfig memory lsc = LICENSE_REGISTRY.getLicensingConfig(
parentIpIds[i],
licenseTemplate,
licenseTermsIds[i]
);
if (lsc.isSet && lsc.commercialRevShare != 0) {
royaltyPercent = lsc.commercialRevShare;
}
rPercents[i] = royaltyPercent;
rPolicies[i] = royaltyPolicy;
}
Expand Down Expand Up @@ -366,6 +374,24 @@ contract LicensingModule is
uint256 licenseTermsId,
Licensing.LicensingConfig memory licensingConfig
) external verifyPermission(ipId) whenNotPaused {
if (licenseTemplate == address(0) && licensingConfig.commercialRevShare != 0) {
revert Errors.LicensingModule__LicenseTemplateCannotBeZeroAddressToOverrideRoyaltyPercent();
}

if (licensingConfig.commercialRevShare != 0) {
ILicenseTemplate lct = ILicenseTemplate(licenseTemplate);
if (!LICENSE_REGISTRY.isRegisteredLicenseTemplate(licenseTemplate)) {
revert Errors.LicenseRegistry__UnregisteredLicenseTemplate(licenseTemplate);
}
if (!lct.canOverrideRoyaltyPercent(licenseTermsId, licensingConfig.commercialRevShare)) {
revert Errors.LicensingModule__CurrentLicenseNotAllowOverrideRoyaltyPercent(
licenseTemplate,
licenseTermsId,
licensingConfig.commercialRevShare
);
}
}

if (
licensingConfig.licensingHook != address(0) &&
(!licensingConfig.licensingHook.supportsInterface(type(ILicensingHook).interfaceId) ||
Expand Down Expand Up @@ -529,7 +555,10 @@ contract LicensingModule is
uint256 mintingFeeByLicense = 0;
address currencyToken = address(0);
(royaltyPolicy, royaltyPercent, mintingFeeByLicense, currencyToken) = lct.getRoyaltyPolicy(licenseTermsId);

// override royalty percent if it is set in licensing config
if (licensingConfig.isSet && licensingConfig.commercialRevShare != 0) {
royaltyPercent = licensingConfig.commercialRevShare;
}
if (royaltyPolicy != address(0)) {
ROYALTY_MODULE.onLicenseMinting(parentIpId, royaltyPolicy, royaltyPercent, royaltyContext);
uint256 tmf = _getTotalMintingFee(licensingConfig, mintingFeeByHook, mintingFeeByLicense, amount);
Expand Down
11 changes: 11 additions & 0 deletions contracts/modules/licensing/PILicenseTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,17 @@ contract PILicenseTemplate is
return _getPILicenseTemplateStorage().licenseTermsCounter;
}

/// @notice Verifies if the royalty percentage defined in the licenseTermsId can be overridden with
/// the given newRoyaltyPercent.
/// @param licenseTermsId The ID of the license terms.
/// @param newRoyaltyPercent The new royalty percentage.
/// @return True if the royalty percentage can be overridden, false otherwise.
function canOverrideRoyaltyPercent(uint256 licenseTermsId, uint32 newRoyaltyPercent) external view returns (bool) {
if (licenseTermsId == 0 || newRoyaltyPercent == 0) return false;
PILTerms memory terms = _getPILicenseTemplateStorage().licenseTerms[licenseTermsId];
return terms.commercialUse;
}

/// @notice checks the contract whether supports the given interface.
function supportsInterface(
bytes4 interfaceId
Expand Down
8 changes: 5 additions & 3 deletions contracts/registries/LicenseRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,11 @@ contract LicenseRegistry is ILicenseRegistry, AccessManagedUpgradeable, UUPSUpgr
isSet: licensingConfig.isSet,
mintingFee: licensingConfig.mintingFee,
licensingHook: licensingConfig.licensingHook,
hookData: licensingConfig.hookData
hookData: licensingConfig.hookData,
commercialRevShare: licensingConfig.commercialRevShare
});

emit LicensingConfigSetForLicense(ipId, licenseTemplate, licenseTermsId);
emit LicensingConfigSetForLicense(ipId, licenseTemplate, licenseTermsId, licensingConfig);
}

/// @notice Sets the LicensingConfig for an IP and applies it to all licenses attached to the IP.
Expand All @@ -167,7 +168,8 @@ contract LicenseRegistry is ILicenseRegistry, AccessManagedUpgradeable, UUPSUpgr
isSet: licensingConfig.isSet,
mintingFee: licensingConfig.mintingFee,
licensingHook: licensingConfig.licensingHook,
hookData: licensingConfig.hookData
hookData: licensingConfig.hookData,
commercialRevShare: licensingConfig.commercialRevShare
});
emit LicensingConfigSetForIP(ipId, licensingConfig);
}
Expand Down
4 changes: 4 additions & 0 deletions test/foundry/mocks/module/MockLicenseTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,8 @@ contract MockLicenseTemplate is BaseLicenseTemplateUpgradeable {
function getLicenseTermsURI(uint256 licenseTermsId) external view returns (string memory) {
return "";
}

function canOverrideRoyaltyPercent(uint256 licenseTermsId, uint32 newRoyaltyPercent) external view returns (bool) {
return true;
}
}
Loading

0 comments on commit a50c930

Please sign in to comment.