Skip to content
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

Replace 0xSplits with new ERC20 Royalty Vault #26

Merged
merged 29 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
44ec959
fix format command
Spablob Mar 26, 2024
8b74398
add solhint ignore
Spablob Mar 26, 2024
c9c5310
add oppenzeppelin v4 contracts
Spablob Mar 26, 2024
ec062d7
update total token supply comments
Spablob Mar 26, 2024
65a650e
[wip] Ip pool intermediate commit
Spablob Mar 26, 2024
e449d96
remove oppenzeppelin contract folder
Spablob Mar 29, 2024
eab0b62
add oppenzeppelin v4 to package.json and yarn.lock
Spablob Mar 29, 2024
c7faf3a
remove ancestors vault contract
Spablob Mar 29, 2024
0c95744
minor adjustments on base test and deploy helper files
Spablob Mar 29, 2024
6ca812e
comment fix
Spablob Mar 29, 2024
9948ec9
update error.sol
Spablob Mar 29, 2024
e889752
remove liquid split related interfaces and test adjustments
Spablob Mar 29, 2024
25c7c45
Add ip pool and LAP royalty policy contract and tests adjustments
Spablob Mar 29, 2024
dac4562
fix(test): Integration with new royalty policy system
jdubpark Mar 30, 2024
b64602e
fix(script): Script change for new royalty policy system
jdubpark Mar 30, 2024
06cde7a
fix: rebase
jdubpark Mar 30, 2024
d7f97c3
fix: remove ERC1155 holder
jdubpark Mar 30, 2024
07d3be2
comment fix
Spablob Mar 30, 2024
bf10d6a
rename to IpRoyaltyVault
Spablob Mar 30, 2024
27c7346
change oppenzeppellin v4 contracts to upgradeable
Spablob Mar 31, 2024
575f1f4
add beacon upgradeability to IpRoyaltyVault
Spablob Mar 31, 2024
e3cb7f5
rename to addIpRoyaltyVaultTokens
Spablob Mar 31, 2024
9bd936a
constructor fix
Spablob Mar 31, 2024
d855ce0
rename claimer to ancestors
Spablob Mar 31, 2024
566f5db
fix(upgrade): OZ upgrade immutable comment
jdubpark Mar 31, 2024
45bad39
fix(tmp): Disable storage check that errors on node_modules check
jdubpark Mar 31, 2024
2def6f6
add amount to event and adjust claimed event
Spablob Mar 31, 2024
c82cd29
event fix
Spablob Mar 31, 2024
f89fbb9
comment fix
Spablob Mar 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .solhintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/contracts/modules/royalty/policies/oppenzeppelin
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ slither :; slither ./contracts

# glob doesn't work for nested folders, so we do it manually
format:
npx prettier --write contracts/*.sol
npx prettier --write contracts/**/*.sol
npx prettier --write contracts

# generate forge coverage on pinned mainnet fork
# process lcov file, ignore test, script, and contracts/mocks folders
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;

import { IERC20 } from "@openzeppelin/contracts-v4/token/ERC20/IERC20.sol";

/// @title Ip royalty vault interface
interface IIpRoyaltyVault is IERC20 {
/// @notice Event emitted when a claim is made
/// @param claimerIpId The claimer ipId address
event Claimed(address claimerIpId);

/// @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);

/// @notice Adds a new revenue token to the pool
/// @param token The address of the revenue token
/// @dev Only callable by the royalty policy LAP
function updateIpRoyaltyVaultTokens(address token) external;

/// @notice A function to snapshot the claimable revenue and royalty token amounts
/// @return The snapshot id
function snapshot() external returns (uint256);

/// @notice A function to calculate the amount of revenue token claimable by a token holder at certain snapshot
/// @param account The address of the token holder
/// @param snapshotId The snapshot id
/// @param token The revenue token to claim
/// @return The amount of revenue token claimable
function claimableRevenue(address account, uint256 snapshotId, address token) external view returns (uint256);

/// @notice Allows token holders to claim revenue token based on the token balance at certain snapshot
/// @param snapshotId The snapshot id
/// @param tokens The list of revenue tokens to claim
function claimRevenueByTokenBatch(uint256 snapshotId, address[] calldata tokens) external;

/// @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;

/// @notice Allows ancestors to claim the royalty tokens and any accrued revenue tokens
/// @param claimerIpId The ip id of the claimer
function collectRoyaltyTokens(address claimerIpId) external;

/// @notice Returns the list of revenue tokens in the pool
/// @return The list of revenue tokens
function getPoolTokens() external view returns (address[] memory);
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.23;

import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import { IRoyaltyPolicy } from "../../../../interfaces/modules/royalty/policies/IRoyaltyPolicy.sol";

/// @title RoyaltyPolicy interface
interface IRoyaltyPolicyLAP is IRoyaltyPolicy {
/// @notice Event emitted when a policy is initialized
/// @param ipId The ID of the IP asset that the policy is being initialized for
/// @param splitClone The split clone address
/// @param ancestorsVault The ancestors vault address
/// @param IpRoyaltyVault The ip royalty vault address
/// @param royaltyStack The royalty stack
/// @param targetAncestors The ip ancestors array
/// @param targetRoyaltyAmount The ip royalty amount array
event PolicyInitialized(
address ipId,
address splitClone,
address ancestorsVault,
address IpRoyaltyVault,
uint32 royaltyStack,
address[] targetAncestors,
uint32[] targetRoyaltyAmount
);

/// @notice Returns the percentage scale - 1000 rnfts represents 100%
function TOTAL_RNFT_SUPPLY() external view returns (uint32);
/// @notice Returns the percentage scale - represents 100% of royalty tokens for an ip
function TOTAL_RT_SUPPLY() external view returns (uint32);

/// @notice Returns the maximum number of parents
function MAX_PARENTS() external view returns (uint256);
Expand All @@ -39,58 +35,17 @@ interface IRoyaltyPolicyLAP is IRoyaltyPolicy {
/// @notice Returns the LicensingModule address
function LICENSING_MODULE() external view returns (address);

/// @notice Returns the 0xSplits LiquidSplitFactory address
function LIQUID_SPLIT_FACTORY() external view returns (address);

/// @notice Returns the 0xSplits LiquidSplitMain address
function LIQUID_SPLIT_MAIN() external view returns (address);

/// @notice Returns the Ancestors Vault Implementation address
function ancestorsVaultImpl() external view returns (address);

/// @notice Distributes funds internally so that accounts holding the royalty nfts at distribution moment can
/// claim afterwards
/// @dev This call will revert if the caller holds all the royalty nfts of the ipId - in that case can call
/// claimFromIpPoolAsTotalRnftOwner() instead
/// @param ipId The ipId whose received funds will be distributed
/// @param token The token to distribute
/// @param accounts The accounts to distribute to
/// @param distributorAddress The distributor address (if any)
function distributeIpPoolFunds(
address ipId,
address token,
address[] calldata accounts,
address distributorAddress
) external;

/// @notice Claims the available royalties for a given address
/// @dev If there are no funds available in split main contract but there are funds in the split clone contract
/// then a distributeIpPoolFunds() call should precede this call
/// @param account The account to claim for
/// @param tokens The tokens to withdraw
function claimFromIpPool(address account, ERC20[] calldata tokens) external;

/// @notice Claims the available royalties for a given address that holds all the royalty nfts of an ipId
/// @dev This call will revert if the caller does not hold all the royalty nfts of the ipId
/// @param ipId The ipId whose received funds will be distributed
/// @param token The token to withdraw
function claimFromIpPoolAsTotalRnftOwner(address ipId, address token) external;

/// @notice Claims available royalty nfts and accrued royalties for an ancestor of a given ipId
/// @param ipId The ipId of the ancestors vault to claim from
/// @param claimerIpId The claimer ipId is the ancestor address that wants to claim
/// @param tokens The ERC20 tokens to withdraw
function claimFromAncestorsVault(address ipId, address claimerIpId, ERC20[] calldata tokens) external;
/// @notice Returns the snapshot interval
function getSnapshotInterval() external view returns (uint256);

/// @notice Returns the royalty data for a given IP asset
/// @param ipId The ID of the IP asset
/// @return isUnlinkable Indicates if the ipId is unlinkable to new parents
/// @return splitClone The address of the liquid split clone contract for a given ipId
/// @return ancestorsVault The address of the ancestors vault contract for a given ipId
/// @return IpRoyaltyVault The ip royalty vault address
/// @return royaltyStack The royalty stack of a given ipId is the sum of the royalties to be paid to each ancestors
/// @return targetAncestors The ip ancestors array
/// @return targetRoyaltyAmount The ip royalty amount array
function getRoyaltyData(
address ipId
) external view returns (bool, address, address, uint32, address[] memory, uint32[] memory);
) external view returns (bool, address, uint32, address[] memory, uint32[] memory);
}
11 changes: 6 additions & 5 deletions contracts/lib/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,12 @@ library Errors {
error RoyaltyPolicyLAP__UnlinkableToParents();
error RoyaltyPolicyLAP__LastPositionNotAbleToMintLicense();

error AncestorsVaultLAP__ZeroRoyaltyPolicyLAP();
error AncestorsVaultLAP__AlreadyClaimed();
error AncestorsVaultLAP__InvalidVault();
error AncestorsVaultLAP__ClaimerNotAnAncestor();
error AncestorsVaultLAP__ERC20BalanceNotZero();
error IpRoyaltyVault__ZeroIpId();
error IpRoyaltyVault__ZeroRoyaltyPolicyLAP();
error IpRoyaltyVault__NotRoyaltyPolicyLAP();
error IpRoyaltyVault__SnapshotIntervalTooShort();
error IpRoyaltyVault__AlreadyClaimed();
error IpRoyaltyVault__ClaimerNotAnAncestor();

////////////////////////////////////////////////////////////////////////////
// ModuleRegistry //
Expand Down
4 changes: 2 additions & 2 deletions contracts/modules/licensing/PILPolicyFrameworkManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ contract PILPolicyFrameworkManager is
/// @param policy The policy to encode
function _policyCommercialTraitsToJson(PILPolicy memory policy) internal pure returns (string memory) {
/* solhint-disable */
// NOTE: TOTAL_RNFT_SUPPLY = 1000 in trait with max_value. For numbers, don't add any display_type, so that
// NOTE: TOTAL_RT_SUPPLY = 100*10**18 in trait with max_value. For numbers, don't add any display_type, so that
// they will show up in the "Ranking" section of the OpenSea UI.
return
string(
Expand All @@ -337,7 +337,7 @@ contract PILPolicyFrameworkManager is
/// @param policy The policy to encode
function _policyDerivativeTraitsToJson(PILPolicy memory policy) internal pure returns (string memory) {
/* solhint-disable */
// NOTE: TOTAL_RNFT_SUPPLY = 1000 in trait with max_value. For numbers, don't add any display_type, so that
// NOTE: TOTAL_RT_SUPPLY = 100*10**18 in trait with max_value. For numbers, don't add any display_type, so that
// they will show up in the "Ranking" section of the OpenSea UI.
return
string(
Expand Down
2 changes: 1 addition & 1 deletion contracts/modules/royalty/RoyaltyModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ contract RoyaltyModule is

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 the receiver ip can have a zero royalty policy since that could mean it is an ip a root
// royalties while the receiver ip can have a zero royalty policy since that could mean it is an ip a root
if (payerRoyaltyPolicy == address(0)) revert Errors.RoyaltyModule__NoRoyaltyPolicySet();
if (!$.isWhitelistedRoyaltyPolicy[payerRoyaltyPolicy])
revert Errors.RoyaltyModule__NotWhitelistedRoyaltyPolicy();
Expand Down
Loading
Loading