Skip to content

Commit

Permalink
Royalty fixes (#78)
Browse files Browse the repository at this point in the history
* royalty fixes

* add the removed restriction back

* format fix

---------

Co-authored-by: Leo Chen <chhao4u@gmail.com>
  • Loading branch information
Spablob and LeoHChen authored Apr 12, 2024
1 parent fed4a6c commit 6696e3b
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 275 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ interface IIpRoyaltyVault {

/// @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;
/// @param tokenList The list of revenue tokens to claim
function claimRevenueByTokenBatch(uint256 snapshotId, address[] calldata tokenList) 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
Expand Down
3 changes: 1 addition & 2 deletions contracts/modules/royalty/RoyaltyModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ contract RoyaltyModule is
/// @param accessManager The address of the protocol admin roles contract
function initialize(address accessManager) external initializer {
if (accessManager == address(0)) revert Errors.RoyaltyModule__ZeroAccessManager();

__AccessManaged_init(accessManager);
__ReentrancyGuard_init();
__UUPSUpgradeable_init();
Expand Down Expand Up @@ -134,7 +133,7 @@ contract RoyaltyModule is

// if the node is a root node, then royaltyPolicyIpId will be address(0) and any type of royalty type can be
// selected to mint a license if the node is a derivative node, then the any minted licenses by the derivative
// node should have the same royalty policy as the parent node a derivative node set its royalty policy
// node should have the same royalty policy as the parent node and a derivative node set its royalty policy
// immutably in onLinkToParents() function below
if (royaltyPolicyIpId != royaltyPolicy && royaltyPolicyIpId != address(0))
revert Errors.RoyaltyModule__CanOnlyMintSelectedPolicy();
Expand Down
48 changes: 26 additions & 22 deletions contracts/modules/royalty/policies/IpRoyaltyVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ contract IpRoyaltyVault is IIpRoyaltyVault, ERC20SnapshotUpgradeable, Reentrancy
__ERC20_init(name, symbol);
}

/// @notice Returns the number royalty token decimals
function decimals() public view override returns (uint8) {
return 6;
}
/// @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
Expand All @@ -123,24 +127,24 @@ contract IpRoyaltyVault is IIpRoyaltyVault, ERC20SnapshotUpgradeable, Reentrancy
uint32 unclaimedTokens = $.unclaimedRoyaltyTokens;
$.unclaimedAtSnapshot[snapshotId] = unclaimedTokens;

address[] memory tokens = $.tokens.values();
address[] memory tokenList = $.tokens.values();

for (uint256 i = 0; i < tokens.length; i++) {
uint256 tokenBalance = IERC20Upgradeable(tokens[i]).balanceOf(address(this));
for (uint256 i = 0; i < tokenList.length; i++) {
uint256 tokenBalance = IERC20Upgradeable(tokenList[i]).balanceOf(address(this));
if (tokenBalance == 0) {
$.tokens.remove(tokens[i]);
$.tokens.remove(tokenList[i]);
continue;
}

uint256 newRevenue = tokenBalance - $.claimVaultAmount[tokens[i]] - $.ancestorsVaultAmount[tokens[i]];
uint256 newRevenue = tokenBalance - $.claimVaultAmount[tokenList[i]] - $.ancestorsVaultAmount[tokenList[i]];
if (newRevenue == 0) continue;

uint256 ancestorsTokens = (newRevenue * unclaimedTokens) / totalSupply();
$.ancestorsVaultAmount[tokens[i]] += ancestorsTokens;
$.ancestorsVaultAmount[tokenList[i]] += ancestorsTokens;

uint256 claimableTokens = newRevenue - ancestorsTokens;
$.claimableAtSnapshot[snapshotId][tokens[i]] = claimableTokens;
$.claimVaultAmount[tokens[i]] += claimableTokens;
$.claimableAtSnapshot[snapshotId][tokenList[i]] = claimableTokens;
$.claimVaultAmount[tokenList[i]] += claimableTokens;
}

emit SnapshotCompleted(snapshotId, block.timestamp, unclaimedTokens);
Expand All @@ -159,19 +163,19 @@ contract IpRoyaltyVault is IIpRoyaltyVault, ERC20SnapshotUpgradeable, Reentrancy

/// @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 nonReentrant {
/// @param tokenList The list of revenue tokens to claim
function claimRevenueByTokenBatch(uint256 snapshotId, address[] calldata tokenList) external nonReentrant {
IpRoyaltyVaultStorage storage $ = _getIpRoyaltyVaultStorage();

for (uint256 i = 0; i < tokens.length; i++) {
uint256 claimableToken = _claimableRevenue(msg.sender, snapshotId, tokens[i]);
for (uint256 i = 0; i < tokenList.length; i++) {
uint256 claimableToken = _claimableRevenue(msg.sender, snapshotId, tokenList[i]);
if (claimableToken == 0) continue;

$.isClaimedAtSnapshot[snapshotId][msg.sender][tokens[i]] = true;
$.claimVaultAmount[tokens[i]] -= claimableToken;
IERC20Upgradeable(tokens[i]).safeTransfer(msg.sender, claimableToken);
$.isClaimedAtSnapshot[snapshotId][msg.sender][tokenList[i]] = true;
$.claimVaultAmount[tokenList[i]] -= claimableToken;
IERC20Upgradeable(tokenList[i]).safeTransfer(msg.sender, claimableToken);

emit RevenueTokenClaimed(msg.sender, tokens[i], claimableToken);
emit RevenueTokenClaimed(msg.sender, tokenList[i], claimableToken);
}
}

Expand Down Expand Up @@ -244,19 +248,19 @@ contract IpRoyaltyVault is IIpRoyaltyVault, ERC20SnapshotUpgradeable, Reentrancy
function _collectAccruedTokens(uint256 royaltyTokensToClaim, address ancestorIpId) internal {
IpRoyaltyVaultStorage storage $ = _getIpRoyaltyVaultStorage();

address[] memory tokens = $.tokens.values();
address[] memory tokenList = $.tokens.values();

for (uint256 i = 0; i < tokens.length; ++i) {
for (uint256 i = 0; i < tokenList.length; ++i) {
// the only case in which unclaimedRoyaltyTokens can be 0 is when the vault is empty and everyone claimed
// in which case the call will revert upstream with IpRoyaltyVault__AlreadyClaimed error
uint256 collectAmount = ($.ancestorsVaultAmount[tokens[i]] * royaltyTokensToClaim) /
uint256 collectAmount = ($.ancestorsVaultAmount[tokenList[i]] * royaltyTokensToClaim) /
$.unclaimedRoyaltyTokens;
if (collectAmount == 0) continue;

$.ancestorsVaultAmount[tokens[i]] -= collectAmount;
IERC20Upgradeable(tokens[i]).safeTransfer(ancestorIpId, collectAmount);
$.ancestorsVaultAmount[tokenList[i]] -= collectAmount;
IERC20Upgradeable(tokenList[i]).safeTransfer(ancestorIpId, collectAmount);

emit RevenueTokenClaimed(ancestorIpId, tokens[i], collectAmount);
emit RevenueTokenClaimed(ancestorIpId, tokenList[i], collectAmount);
}
}

Expand Down
1 change: 0 additions & 1 deletion contracts/modules/royalty/policies/RoyaltyPolicyLAP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ contract RoyaltyPolicyLAP is IRoyaltyPolicyLAP, AccessManagedUpgradeable, Reentr
/// @param accessManager The address of the protocol admin roles contract
function initialize(address accessManager) external initializer {
if (accessManager == address(0)) revert Errors.RoyaltyPolicyLAP__ZeroAccessManager();

__AccessManaged_init(accessManager);
__ReentrancyGuard_init();
__UUPSUpgradeable_init();
Expand Down
Loading

0 comments on commit 6696e3b

Please sign in to comment.