From 0650769d43b6005615f261114e114407816c920b Mon Sep 17 00:00:00 2001 From: Spablob Date: Sat, 17 Feb 2024 01:43:42 -0800 Subject: [PATCH] royalty module adjustments --- .../modules/royalty/IRoyaltyModule.sol | 21 +++++++++++++ .../modules/royalty-module/RoyaltyModule.sol | 24 ++++++++++++++ .../modules/royalty/RoyaltyModule.t.sol | 31 +++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/contracts/interfaces/modules/royalty/IRoyaltyModule.sol b/contracts/interfaces/modules/royalty/IRoyaltyModule.sol index 48cf5b249..c85f5f914 100644 --- a/contracts/interfaces/modules/royalty/IRoyaltyModule.sol +++ b/contracts/interfaces/modules/royalty/IRoyaltyModule.sol @@ -29,6 +29,13 @@ interface IRoyaltyModule is IModule { /// @param amount The amount that is paid event RoyaltyPaid(address receiverIpId, address payerIpId, address sender, address token, uint256 amount); + /// @notice Event emitted when the license minting fee is paid + /// @param receiverIpId The ipId that receives the royalties + /// @param payerAddress The address that pays the royalties + /// @param token The token that is used to pay the royalties + /// @param amount The amount paid + event LicenseMintingFeePaid(address receiverIpId, address payerAddress, address token, uint256 amount); + /// @notice Returns the licensing module address function LICENSING_MODULE() external view returns (address); @@ -93,4 +100,18 @@ interface IRoyaltyModule is IModule { /// @param token The token to use to pay the royalties /// @param amount The amount to pay function payRoyaltyOnBehalf(address receiverIpId, address payerIpId, address token, uint256 amount) external; + + /// @notice Allows to pay the minting fee for a license + /// @param receiverIpId The ipId that receives the royalties + /// @param payerAddress The address that pays the royalties + /// @param licenseRoyaltyPolicy The royalty policy of the license being minted + /// @param token The token to use to pay the royalties + /// @param amount The amount to pay + function payLicenseMintingFee( + address receiverIpId, + address payerAddress, + address licenseRoyaltyPolicy, + address token, + uint256 amount + ) external; } diff --git a/contracts/modules/royalty-module/RoyaltyModule.sol b/contracts/modules/royalty-module/RoyaltyModule.sol index 398d8b4e5..397b91e37 100644 --- a/contracts/modules/royalty-module/RoyaltyModule.sol +++ b/contracts/modules/royalty-module/RoyaltyModule.sol @@ -155,6 +155,30 @@ contract RoyaltyModule is IRoyaltyModule, Governable, ReentrancyGuard, BaseModul emit RoyaltyPaid(receiverIpId, payerIpId, msg.sender, token, amount); } + /// @notice Allows to pay the minting fee for a license + /// @param receiverIpId The ipId that receives the royalties + /// @param payerAddress The address that pays the royalties + /// @param licenseRoyaltyPolicy The royalty policy of the license being minted + /// @param token The token to use to pay the royalties + /// @param amount The amount to pay + function payLicenseMintingFee( + address receiverIpId, + address payerAddress, + address licenseRoyaltyPolicy, + address token, + uint256 amount + ) external onlyLicensingModule { + if (!isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken(); + + if (licenseRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet(); + if (!isWhitelistedRoyaltyPolicy[licenseRoyaltyPolicy]) + revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy(); + + IRoyaltyPolicy(licenseRoyaltyPolicy).onRoyaltyPayment(payerAddress, receiverIpId, token, amount); + + emit LicenseMintingFeePaid(receiverIpId, payerAddress, token, amount); + } + /// @notice IERC165 interface support. function supportsInterface(bytes4 interfaceId) public view virtual override(BaseModule, IERC165) returns (bool) { return interfaceId == type(IRoyaltyModule).interfaceId || super.supportsInterface(interfaceId); diff --git a/test/foundry/modules/royalty/RoyaltyModule.t.sol b/test/foundry/modules/royalty/RoyaltyModule.t.sol index bc917752e..388f29d0c 100644 --- a/test/foundry/modules/royalty/RoyaltyModule.t.sol +++ b/test/foundry/modules/royalty/RoyaltyModule.t.sol @@ -14,6 +14,7 @@ contract TestRoyaltyModule is BaseTest { event RoyaltyTokenWhitelistUpdated(address token, bool allowed); event RoyaltyPolicySet(address ipId, address royaltyPolicy, bytes data); event RoyaltyPaid(address receiverIpId, address payerIpId, address sender, address token, uint256 amount); + event LicenseMintingFeePaid(address receiverIpId, address payerAddress, address token, uint256 amount); address internal ipAccount1 = address(0x111000aaa); address internal ipAccount2 = address(0x111000bbb); @@ -488,4 +489,34 @@ contract TestRoyaltyModule is BaseTest { assertEq(payerIpIdUSDCBalBefore - payerIpIdUSDCBalAfter, royaltyAmount); assertEq(splitCloneUSDCBalAfter - splitCloneUSDCBalBefore, royaltyAmount); } + + function test_RoyaltyModule_payLicenseMintingFee() public { + uint256 royaltyAmount = 100 * 10 ** 6; + address receiverIpId = address(7); + address payerAddress = address(3); + address licenseRoyaltyPolicy = address(royaltyPolicyLAP); + address token = address(USDC); + + (, address splitClone, , , ) = royaltyPolicyLAP.royaltyData(receiverIpId); + + vm.startPrank(payerAddress); + USDC.mint(payerAddress, royaltyAmount); + USDC.approve(address(royaltyPolicyLAP), royaltyAmount); + vm.stopPrank; + + uint256 payerAddressUSDCBalBefore = USDC.balanceOf(payerAddress); + uint256 splitCloneUSDCBalBefore = USDC.balanceOf(splitClone); + + vm.expectEmit(true, true, true, true, address(royaltyModule)); + emit LicenseMintingFeePaid(receiverIpId, payerAddress, address(USDC), royaltyAmount); + + vm.startPrank(address(licensingModule)); + royaltyModule.payLicenseMintingFee(receiverIpId, payerAddress, licenseRoyaltyPolicy, token, royaltyAmount); + + uint256 payerAddressUSDCBalAfter = USDC.balanceOf(payerAddress); + uint256 splitCloneUSDCBalAfter = USDC.balanceOf(splitClone); + + assertEq(payerAddressUSDCBalBefore - payerAddressUSDCBalAfter, royaltyAmount); + assertEq(splitCloneUSDCBalAfter - splitCloneUSDCBalBefore, royaltyAmount); + } }