-
Notifications
You must be signed in to change notification settings - Fork 96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Dispute effects on royalty #35
Changes from all commits
224a2b1
7993cde
809f9f3
6cdac10
25bd672
fb2bc1c
213e2b7
e1e5a35
93b3746
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,9 +30,22 @@ interface IRoyaltyModule is IModule { | |
/// @param amount The amount paid | ||
event LicenseMintingFeePaid(address receiverIpId, address payerAddress, address token, uint256 amount); | ||
|
||
/// @notice Sets the licensing module | ||
/// @dev Enforced to be only callable by the protocol admin | ||
/// @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); | ||
|
||
Comment on lines
43
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two can also be removed, as we don't expect the functions to be called by another contract. |
||
/// @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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,20 @@ interface IRoyaltyPolicyLAP is IRoyaltyPolicy { | |
uint32[] targetRoyaltyAmount | ||
); | ||
|
||
/// @notice The state data of the LAP royalty policy | ||
/// @param isUnlinkableToParents Indicates if the ipId is unlinkable to new parents | ||
/// @param ipRoyaltyVault The ip royalty vault address | ||
/// @param royaltyStack The royalty stack of a given ipId is the sum of the royalties to be paid to each ancestors | ||
/// @param ancestorsAddresses The ancestors addresses array | ||
/// @param ancestorsRoyalties Contains royalty token amounts for each ancestor on same index as ancestorsAddresses | ||
struct LAPRoyaltyData { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there any redundancy of those data with license data? |
||
bool isUnlinkableToParents; | ||
address ipRoyaltyVault; | ||
uint32 royaltyStack; | ||
address[] ancestorsAddresses; | ||
uint32[] ancestorsRoyalties; | ||
} | ||
|
||
/// @notice Returns the percentage scale - represents 100% of royalty tokens for an ip | ||
function TOTAL_RT_SUPPLY() external view returns (uint32); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ import { BaseModule } from "../BaseModule.sol"; | |
import { GovernableUpgradeable } from "../../governance/GovernableUpgradeable.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 { Errors } from "../../lib/Errors.sol"; | ||
import { ROYALTY_MODULE_KEY } from "../../lib/modules/Module.sol"; | ||
import { BaseModule } from "../BaseModule.sol"; | ||
|
@@ -27,12 +28,14 @@ contract RoyaltyModule is | |
using ERC165Checker for address; | ||
|
||
/// @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; | ||
|
@@ -66,14 +69,22 @@ contract RoyaltyModule is | |
_; | ||
} | ||
|
||
/// @notice Sets the license registry | ||
/// @notice Sets the licensing module | ||
/// @dev Enforced to be only callable by the protocol admin | ||
/// @param licensing The address of the license registry | ||
/// @param licensing The address of the license module | ||
function setLicensingModule(address licensing) external onlyProtocolAdmin { | ||
if (licensing == address(0)) revert Errors.RoyaltyModule__ZeroLicensingModule(); | ||
_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 onlyProtocolAdmin { | ||
if (dispute == address(0)) revert Errors.RoyaltyModule__ZeroDisputeModule(); | ||
_getRoyaltyModuleStorage().disputeModule = dispute; | ||
} | ||
|
||
Comment on lines
+80
to
+87
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of making this "set" function as a governance function. function updateCoreMetadataModule() external {
coreMetadataModule = IModuleRegistry(MODULE_REGISTRY).getModule(CORE_METADATA_MODULE_KEY);
} in this case, it would be: function updateDisputeModule() external {
_getRoyaltyModuleStorage().disputeModule = IModuleRegistry(MODULE_REGISTRY).getModule(DISPUTE_MODULE_KEY);
} so that the function can be permissionless and maintain code style consistency in our code base. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not advertise this as a "permissionless" method, because the setter of value in ModuleRegistry is still the governance. Simply delegating the reading & setting to the public, where the value is controlled by the governance. But yes, this is a cleaner syntax since we don't need to pass in the dispute module address for each contract. Just update in the Module Registry, and then call I recommend we make this change for all contracts in a separate PR, since most other modules are still using the old style. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. agree, we will leave those changes to next PR @Spablob |
||
/// @notice Whitelist a royalty policy | ||
/// @dev Enforced to be only callable by the protocol admin | ||
/// @param royaltyPolicy The address of the royalty policy | ||
|
@@ -175,6 +186,10 @@ contract RoyaltyModule is | |
RoyaltyModuleStorage storage $ = _getRoyaltyModuleStorage(); | ||
if (!$.isWhitelistedRoyaltyToken[token]) revert Errors.RoyaltyModule__NotWhitelistedRoyaltyToken(); | ||
|
||
IDisputeModule dispute = IDisputeModule($.disputeModule); | ||
if (dispute.isIpTagged(receiverIpId) || dispute.isIpTagged(payerIpId)) | ||
revert Errors.RoyaltyModule__IpIsTagged(); | ||
|
||
address payerRoyaltyPolicy = $.royaltyPolicies[payerIpId]; | ||
// if the payer does not have a royalty policy set, then the payer is not a derivative ip and does not pay | ||
// royalties while the receiver ip can have a zero royalty policy since that could mean it is an ip a root | ||
|
@@ -202,7 +217,7 @@ 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 (licenseRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet(); | ||
if (!$.isWhitelistedRoyaltyPolicy[licenseRoyaltyPolicy]) | ||
revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy(); | ||
|
@@ -217,6 +232,11 @@ 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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unnecessary to include these two functions in the interface, as no other contracts will invoke them. It would be sufficient to define only those functions that are directly related to the functionality of the royalty module. The two configuration functions are specific to the implementation and do not require definition in the interface.