Skip to content

Commit

Permalink
Royalty cross-policy remix (#210)
Browse files Browse the repository at this point in the history
* remove gas limit from ci

* pragma fix

* main royalty contract and interface changes

* remove constants from dispute interfaces

* royalty unit tests

* licensing related changes

* fix integration and invariant tests

* adjust errors.sol

* fix remaining tests

* add group related adjustment in royalty module

* format fix
  • Loading branch information
Spablob authored Aug 27, 2024
1 parent 98af8c8 commit 4d961e5
Show file tree
Hide file tree
Showing 55 changed files with 3,206 additions and 1,907 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/foundry_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:

- name: Run Forge tests
run: |
forge test -vvv --gas-limit 800000000000
forge test -vvv
id: forge-test

- name: Run solhint
Expand Down
2 changes: 1 addition & 1 deletion contracts/IPAccountStorage.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
pragma solidity 0.8.23;

import { IIPAccountStorage } from "./interfaces/IIPAccountStorage.sol";
import { IModuleRegistry } from "./interfaces/registries/IModuleRegistry.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IIPAccountStorage.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
// See https://github.com/storyprotocol/protocol-contracts/blob/main/StoryProtocol-AlphaTestingAgreement-17942166.3.pdf
pragma solidity ^0.8.23;
pragma solidity 0.8.23;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/modules/base/IViewModule.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
// See https://github.com/storyprotocol/protocol-contracts/blob/main/StoryProtocol-AlphaTestingAgreement-17942166.3.pdf
pragma solidity ^0.8.23;
pragma solidity 0.8.23;

import { IModule } from "./IModule.sol";

Expand Down
3 changes: 0 additions & 3 deletions contracts/interfaces/modules/dispute/IDisputeModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,6 @@ interface IDisputeModule {
/// @param disputeId The dispute id
event DisputeResolved(uint256 disputeId);

/// @notice Tag to represent the dispute is in dispute state waiting for judgement
function IN_DISPUTE() external view returns (bytes32);

/// @notice Dispute ID counter
function disputeCounter() external view returns (uint256);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,6 @@ pragma solidity 0.8.23;

/// @title Arbitration Policy Interface
interface IArbitrationPolicy {
/// @notice Returns the protocol-wide dispute module address
function DISPUTE_MODULE() external view returns (address);

/// @notice Returns the payment token address
function PAYMENT_TOKEN() external view returns (address);

/// @notice Returns the arbitration price
function ARBITRATION_PRICE() external view returns (uint256);

/// @notice Returns the treasury address
function treasury() external view returns (address);

/// @notice Allows governance set the treasury address
/// @dev Enforced to be only callable by the governance protocol admin
/// @param newTreasury The new address of the treasury
Expand Down Expand Up @@ -46,4 +34,7 @@ interface IArbitrationPolicy {
/// @param disputeId The dispute id
/// @param data The arbitrary data used to resolve the dispute
function onResolveDispute(address caller, uint256 disputeId, bytes calldata data) external;

/// @notice Returns the treasury address
function treasury() external view returns (address);
}
4 changes: 2 additions & 2 deletions contracts/interfaces/modules/licensing/ILicenseTemplate.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ interface ILicenseTemplate is IERC165 {
/// the license term does set RoyaltyPolicy.
/// @param licenseTermsId The ID of the license terms.
/// @return royaltyPolicy The address of the royalty policy specified for the license terms.
/// @return royaltyData The data of the royalty policy.
/// @return royaltyPercent The percentage of the royalty.
/// @return mintingLicenseFee The fee for minting a license.
/// @return currencyToken The address of the ERC20 token, used for minting license fee and royalties.
/// the currency token will used for pay for license token minting fee and royalties.
Expand All @@ -80,7 +80,7 @@ interface ILicenseTemplate is IERC165 {
)
external
view
returns (address royaltyPolicy, bytes memory royaltyData, uint256 mintingLicenseFee, address currencyToken);
returns (address royaltyPolicy, uint32 royaltyPercent, uint256 mintingLicenseFee, address currencyToken);

/// @notice Verifies the minting of a license token.
/// @dev the function will be called by the LicensingModule when minting a license token to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
pragma solidity 0.8.23;

import { IModule } from "../../../../contracts/interfaces/modules/base/IModule.sol";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;
pragma solidity 0.8.23;

import { IViewModule } from "../base/IViewModule.sol";

Expand Down
93 changes: 65 additions & 28 deletions contracts/interfaces/modules/royalty/IRoyaltyModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,26 @@ interface IRoyaltyModule is IModule {
/// @param amount The amount paid
event LicenseMintingFeePaid(address receiverIpId, address payerAddress, address token, uint256 amount);

/// @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
function isWhitelistedRoyaltyPolicy(address royaltyPolicy) external view returns (bool);
/// @notice Event emitted when a royalty policy is registered
/// @param externalRoyaltyPolicy The address of the external royalty policy
event ExternalRoyaltyPolicyRegistered(address externalRoyaltyPolicy);

/// @notice Indicates if a royalty token is whitelisted
/// @param token The address of the royalty token
/// @return isWhitelisted True if the royalty token is whitelisted
function isWhitelistedRoyaltyToken(address token) external view returns (bool);
/// @notice Event emitted when the IP graph limits are updated
/// @param maxParents The maximum number of parents an IP asset can have
/// @param maxAncestors The maximum number of ancestors an IP asset can have
/// @param accumulatedRoyaltyPoliciesLimit The maximum number of accumulated royalty policies an IP asset can have
event IpGraphLimitsUpdated(uint256 maxParents, uint256 maxAncestors, uint256 accumulatedRoyaltyPoliciesLimit);

/// @notice Indicates the royalty policy for a given IP asset
/// @param ipId The ID of IP asset
/// @return royaltyPolicy The address of the royalty policy
function royaltyPolicies(address ipId) external view returns (address);
/// @notice Sets the ip graph limits
/// @dev Enforced to be only callable by the protocol admin
/// @param parentLimit The maximum number of parents an IP asset can have
/// @param ancestorLimit The maximum number of ancestors an IP asset can have
/// @param accumulatedRoyaltyPoliciesLimit The maximum number of accumulated royalty policies an IP asset can have
function setIpGraphLimits(
uint256 parentLimit,
uint256 ancestorLimit,
uint256 accumulatedRoyaltyPoliciesLimit
) external;

/// @notice Whitelist a royalty policy
/// @dev Enforced to be only callable by the protocol admin
Expand All @@ -57,52 +63,83 @@ interface IRoyaltyModule is IModule {
/// @param allowed Indicates if the token is whitelisted or not
function whitelistRoyaltyToken(address token, bool allowed) external;

/// @notice Registers an external royalty policy
/// @param externalRoyaltyPolicy The address of the external royalty policy
function registerExternalRoyaltyPolicy(address externalRoyaltyPolicy) external;

/// @notice Executes royalty related logic on license minting
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The ipId whose license is being minted (licensor)
/// @param royaltyPolicy The royalty policy address of the license being minted
/// @param licenseData The license data custom to each the royalty policy
/// @param licensePercent The license percentage of the license being minted
/// @param externalData The external data custom to each the royalty policy
function onLicenseMinting(
address ipId,
address royaltyPolicy,
bytes calldata licenseData,
uint32 licensePercent,
bytes calldata externalData
) external;

/// @notice Executes royalty related logic on linking to parents
/// @dev Enforced to be only callable by LicensingModule
/// @param ipId The children ipId that is being linked to parents
/// @param royaltyPolicy The common royalty policy address of all the licenses being burned
/// @param parentIpIds The parent ipIds that the children ipId is being linked to
/// @param licenseData The license data custom to each the royalty policy
/// @param licensesPercent The license percentage of the licenses being minted
/// @param externalData The external data custom to each the royalty policy
function onLinkToParents(
address ipId,
address royaltyPolicy,
address[] calldata parentIpIds,
bytes[] memory licenseData,
address[] calldata licenseRoyaltyPolicies,
uint32[] calldata licensesPercent,
bytes calldata externalData
) external;

/// @notice Allows the function caller to pay royalties to the receiver IP asset on behalf of the payer IP asset.
/// @param receiverIpId The ID of the IP asset that receives the royalties
/// @param payerIpId The ID of the IP asset that pays the royalties
/// @param receiverIpId The ipId that receives the royalties
/// @param payerIpId The ipId that pays the royalties
/// @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;
function payLicenseMintingFee(address receiverIpId, address payerAddress, address token, uint256 amount) external;

/// @notice Returns the total number of royalty tokens
function totalRtSupply() external pure returns (uint32);

/// @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
function isWhitelistedRoyaltyPolicy(address royaltyPolicy) external view returns (bool);

/// @notice Indicates if an external royalty policy is registered
/// @param externalRoyaltyPolicy The address of the external royalty policy
/// @return isRegistered True if the external royalty policy is registered
function isRegisteredExternalRoyaltyPolicy(address externalRoyaltyPolicy) external view returns (bool);

/// @notice Indicates if a royalty token is whitelisted
/// @param token The address of the royalty token
/// @return isWhitelisted True if the royalty token is whitelisted
function isWhitelistedRoyaltyToken(address token) external view returns (bool);

/// @notice Returns the maximum number of parents
function maxParents() external view returns (uint256);

/// @notice Returns the maximum number of total ancestors
function maxAncestors() external view returns (uint256);

/// @notice Returns the maximum number of accumulated royalty policies an IP asset can have
function maxAccumulatedRoyaltyPolicies() external view returns (uint256);

/// @notice Indicates the royalty vault for a given IP asset
/// @param ipId The ID of IP asset
function ipRoyaltyVaults(address ipId) external view returns (address);

/// @notice Returns the accumulated royalty policies for a given IP asset
/// @param ipId The ID of IP asset
function accumulatedRoyaltyPolicies(address ipId) external view returns (address[] memory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;

/// @title IExternalRoyaltyPolicy interface
interface IExternalRoyaltyPolicy {
/// @notice Returns the amount of royalty tokens required to link a child to a given IP asset
/// @param ipId The ipId of the IP asset
/// @param licensePercent The percentage of the license
/// @return The amount of royalty tokens required to link a child to a given IP asset
function rtsRequiredToLink(address ipId, uint32 licensePercent) external view returns (uint32);
}
70 changes: 27 additions & 43 deletions contracts/interfaces/modules/royalty/policies/IIpRoyaltyVault.sol
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

/// @title Ip royalty vault interface
/// @title IpRoyaltyVault interface
interface IIpRoyaltyVault {
/// @notice Event emitted when royalty tokens are collected
/// @param ancestorIpId The ancestor ipId address
/// @param royaltyTokensCollected The amount of royalty tokens collected
event RoyaltyTokensCollected(address ancestorIpId, uint256 royaltyTokensCollected);
/// @notice Event emitted when a revenue token is added to a vault
/// @param token The address of the revenue token
/// @param vault The address of the vault
event RevenueTokenAddedToVault(address token, address vault);

/// @notice Event emitted when a snapshot is taken
/// @param snapshotId The snapshot id
/// @param snapshotTimestamp The timestamp of the snapshot
/// @param unclaimedTokens The amount of unclaimed tokens at the snapshot
event SnapshotCompleted(uint256 snapshotId, uint256 snapshotTimestamp, uint32 unclaimedTokens);
event SnapshotCompleted(uint256 snapshotId, uint256 snapshotTimestamp);

/// @notice Event emitted when a revenue token is claimed
/// @param claimer The address of the claimer
/// @param token The revenue token claimed
/// @param amount The amount of revenue token claimed
event RevenueTokenClaimed(address claimer, address token, uint256 amount);

/// @notice initializer for this implementation contract
/// @notice Initializer for this implementation contract
/// @param name The name of the royalty token
/// @param symbol The symbol of the royalty token
/// @param supply The total supply of the royalty token
/// @param unclaimedTokens The amount of unclaimed royalty tokens reserved for ancestors
/// @param ipIdAddress The ip id the royalty vault belongs to
/// @param rtReceiver The address of the royalty token receiver
function initialize(
string memory name,
string memory symbol,
uint32 supply,
uint32 unclaimedTokens,
address ipIdAddress
address ipIdAddress,
address rtReceiver
) external;

/// @notice Adds a new revenue token to the vault
/// @param token The address of the revenue token
/// @dev Only callable by the royalty policy LAP
/// @return Whether the token is added
function addIpRoyaltyVaultTokens(address token) external returns (bool);
/// @dev Only callable by the royalty module or whitelisted royalty policy
function addIpRoyaltyVaultTokens(address token) external;

/// @notice A function to snapshot the claimable revenue and royalty token amounts
/// @return The snapshot id
Expand All @@ -59,40 +57,30 @@ interface IIpRoyaltyVault {
/// @notice Allows token holders to claim by a list of snapshot ids based on the token balance at certain snapshot
/// @param snapshotIds The list of snapshot ids
/// @param token The revenue token to claim
function claimRevenueBySnapshotBatch(uint256[] memory snapshotIds, address token) external;
/// @return The amount of revenue tokens claimed
function claimRevenueBySnapshotBatch(uint256[] memory snapshotIds, address token) external returns (uint256);

/// @notice Allows ancestors to claim the royalty tokens and any accrued revenue tokens
/// @param ancestorIpId The ip id of the ancestor to whom the royalty tokens belong to
function collectRoyaltyTokens(address ancestorIpId) external;
/// @notice Allows to claim revenue tokens on behalf of the ip royalty vault
/// @param snapshotId The snapshot id
/// @param tokenList The list of revenue tokens to claim
/// @param targetIpId The target ip id to claim revenue tokens from
function claimByTokenBatchAsSelf(uint256 snapshotId, address[] calldata tokenList, address targetIpId) external;

/// @notice Collect the accrued tokens (if any)
/// @param ancestorIpId The ip id of the ancestor to whom the royalty tokens belong to
/// @param tokens The list of revenue tokens to claim
function collectAccruedTokens(address ancestorIpId, address[] calldata tokens) external;
/// @notice Allows to claim revenue tokens on behalf of the ip royalty vault by snapshot batch
/// @param snapshotIds The list of snapshot ids
/// @param token The revenue token to claim
/// @param targetIpId The target ip id to claim revenue tokens from
function claimBySnapshotBatchAsSelf(uint256[] memory snapshotIds, address token, address targetIpId) external;

/// @notice Returns the current snapshot id
function getCurrentSnapshotId() external view returns (uint256);

/// @notice The ip id to whom this royalty vault belongs to
/// @return The ip id address
function ipId() external view returns (address);

/// @notice The amount of unclaimed royalty tokens
function unclaimedRoyaltyTokens() external view returns (uint32);

/// @notice The last snapshotted timestamp
function lastSnapshotTimestamp() external view returns (uint256);

/// @notice The amount of revenue token in the ancestors vault
/// @param token The address of the revenue token
function ancestorsVaultAmount(address token) external view returns (uint256);

/// @notice The amount of revenue tokens that can be collected by the ancestor
/// @param ancestorIpId The ancestor ipId address
/// @param token The address of the revenue token
function collectableAmount(address ancestorIpId, address token) external view returns (uint256);

/// @notice Indicates whether the ancestor has collected the royalty tokens
/// @param ancestorIpId The ancestor ipId address
function isCollectedByAncestor(address ancestorIpId) external view returns (bool);

/// @notice Amount of revenue token in the claim vault
/// @param token The address of the revenue token
function claimVaultAmount(address token) external view returns (uint256);
Expand All @@ -102,10 +90,6 @@ interface IIpRoyaltyVault {
/// @param token The address of the revenue token
function claimableAtSnapshot(uint256 snapshotId, address token) external view returns (uint256);

/// @notice Amount of unclaimed revenue tokens at the snapshot
/// @param snapshotId The snapshot id
function unclaimedAtSnapshot(uint256 snapshotId) external view returns (uint32);

/// @notice Indicates whether the claimer has claimed the revenue tokens at a given snapshot
/// @param snapshotId The snapshot id
/// @param claimer The address of the claimer
Expand Down
Loading

0 comments on commit 4d961e5

Please sign in to comment.