Skip to content

Commit

Permalink
fix(royalty): update for core protocol royalty policy changes (storyp…
Browse files Browse the repository at this point in the history
  • Loading branch information
sebsadface authored Dec 11, 2024
1 parent b81fad5 commit f4d1823
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 245 deletions.
23 changes: 0 additions & 23 deletions contracts/interfaces/workflows/IRoyaltyWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,6 @@ pragma solidity 0.8.26;
/// @title Royalty Workflows Interface
/// @notice Interface for IP royalty workflows.
interface IRoyaltyWorkflows {
/// @notice Transfers specified amounts of royalties from various royalty policies to the royalty
/// vault of an ancestor IP, and claims all the revenue for each currency token from the
/// ancestor IP's royalty vault to the claimer.
/// @param ancestorIpId The address of the ancestor IP from which the revenue is being claimed.
/// @param claimer The address of the claimer of the currency (revenue) tokens.
/// @param childIpIds The addresses of the child IPs from which royalties are derived.
/// @param royaltyPolicies The addresses of the royalty policies, where royaltyPolicies[i] governs
/// the royalty flow for childIpIds[i].
/// @param currencyTokens The addresses of the currency tokens in which royalties will be claimed,
/// where currencyTokens[i] is the token used for royalties from childIpIds[i].
/// @param amounts The amounts to transfer and claim, where amounts[i] represents the amount of
/// royalties in currencyTokens[i] to transfer from childIpIds[i]'s royaltyPolicies[i] to the ancestor's
/// royalty vault.
/// @return amountsClaimed The amounts of successfully claimed revenue for each specified currency token.
function transferToVaultAndClaimByTokenBatch(
address ancestorIpId,
address claimer,
address[] calldata childIpIds,
address[] calldata royaltyPolicies,
address[] calldata currencyTokens,
uint256[] calldata amounts
) external returns (uint256[] memory amountsClaimed);

/// @notice Transfers all avaiable royalties from various royalty policies to the royalty
/// vault of an ancestor IP, and claims all the revenue for each currency token
/// from the ancestor IP's royalty vault to the claimer.
Expand Down
61 changes: 1 addition & 60 deletions contracts/workflows/RoyaltyWorkflows.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,48 +43,6 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
__UUPSUpgradeable_init();
}

/// @notice Transfers specified amounts of royalties from various royalty policies to the royalty
/// vault of an ancestor IP, and claims all the revenue for each currency token from the
/// ancestor IP's royalty vault to the claimer.
/// @param ancestorIpId The address of the ancestor IP from which the revenue is being claimed.
/// @param claimer The address of the claimer of the currency (revenue) tokens.
/// @param childIpIds The addresses of the child IPs from which royalties are derived.
/// @param royaltyPolicies The addresses of the royalty policies, where royaltyPolicies[i] governs
/// the royalty flow for childIpIds[i].
/// @param currencyTokens The addresses of the currency tokens in which royalties will be claimed,
/// where currencyTokens[i] is the token used for royalties from childIpIds[i].
/// @param amounts The amounts to transfer and claim, where amounts[i] represents the amount of
/// royalties in currencyTokens[i] to transfer from childIpIds[i]'s royaltyPolicies[i] to the ancestor's
/// royalty vault.
/// @return amountsClaimed The amounts of successfully claimed revenue for each specified currency token.
function transferToVaultAndClaimByTokenBatch(
address ancestorIpId,
address claimer,
address[] calldata childIpIds,
address[] calldata royaltyPolicies,
address[] calldata currencyTokens,
uint256[] calldata amounts
) external returns (uint256[] memory amountsClaimed) {
// Transfers to ancestor's vault an amount of revenue tokens claimable via the given royalty policy
for (uint256 i = 0; i < childIpIds.length; i++) {
IGraphAwareRoyaltyPolicy(royaltyPolicies[i]).transferToVault({
ipId: childIpIds[i],
ancestorIpId: ancestorIpId,
token: currencyTokens[i],
amount: amounts[i]
});
}

// Gets the ancestor IP's royalty vault
IIpRoyaltyVault ancestorIpRoyaltyVault = IIpRoyaltyVault(ROYALTY_MODULE.ipRoyaltyVaults(ancestorIpId));

// Claims revenue for each specified currency token
amountsClaimed = ancestorIpRoyaltyVault.claimRevenueOnBehalfByTokenBatch({
claimer: claimer,
tokenList: _getUniqueCurrencyTokens(currencyTokens)
});
}

/// @notice Transfers all avaiable royalties from various royalty policies to the royalty
/// vault of an ancestor IP, and claims all the revenue for each currency token
/// from the ancestor IP's royalty vault to the claimer.
Expand All @@ -104,28 +62,11 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
address[] calldata currencyTokens
) external returns (uint256[] memory amountsClaimed) {
for (uint256 i = 0; i < childIpIds.length; i++) {
// Gets the total lifetime revenue tokens received for a given IP asset
uint256 totalTokenReceivedByChild = ROYALTY_MODULE.totalRevenueTokensReceived({
ipId: childIpIds[i],
token: currencyTokens[i]
});

// Gets the total lifetime revenue tokens transferred to a vault from a descendant IP via the policy
uint256 totalTokenTransferredToAncestor = IGraphAwareRoyaltyPolicy(royaltyPolicies[i])
.getTransferredTokens({ ipId: childIpIds[i], ancestorIpId: ancestorIpId, token: currencyTokens[i] });

uint32 ancestorPercentage = IGraphAwareRoyaltyPolicy(royaltyPolicies[i]).getPolicyRoyalty({
ipId: childIpIds[i],
ancestorIpId: ancestorIpId
});

// Transfer all available revenue tokens to the ancestor's vault
IGraphAwareRoyaltyPolicy(royaltyPolicies[i]).transferToVault({
ipId: childIpIds[i],
ancestorIpId: ancestorIpId,
token: currencyTokens[i],
amount: ((totalTokenReceivedByChild * ancestorPercentage) / ROYALTY_MODULE.maxPercent()) -
totalTokenTransferredToAncestor
token: currencyTokens[i]
});
}

Expand Down
3 changes: 0 additions & 3 deletions docs/WORKFLOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@

### [Royalty Workflows](../contracts/interfaces/workflows/IRoyaltyWorkflows.sol)

- `transferToVaultAndClaimByTokenBatch`:
- Transfers specified amounts of royalties from various royalty policies to the royalty vault of the ancestor IP -> Claims all the revenue in each currency token from the ancestor IP's royalty vault to the claimer.

- `claimAllRevenue`:
- Transfers all avaiable royalties from various royalty policies to the royalty vault of the ancestor IP -> Claims all the revenue in each currency token from the ancestor IP's royalty vault to the claimer.

Expand Down
14 changes: 2 additions & 12 deletions test/integration/workflows/GroupingIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -261,23 +261,13 @@ contract GroupingIntegration is BaseIntegration {
StoryUSD.mint(testSender, amount1);
StoryUSD.approve(address(royaltyModule), amount1);
royaltyModule.payRoyaltyOnBehalf(ipId1, testSender, address(StoryUSD), amount1);
IGraphAwareRoyaltyPolicy(royaltyPolicyLAPAddr).transferToVault(
ipId1,
newGroupId,
address(StoryUSD),
(amount1 * revShare) / royaltyModule.maxPercent()
);
IGraphAwareRoyaltyPolicy(royaltyPolicyLAPAddr).transferToVault(ipId1, newGroupId, address(StoryUSD));

uint256 amount2 = 10_000 * 10 ** StoryUSD.decimals(); // 10,000 tokens
StoryUSD.mint(testSender, amount2);
StoryUSD.approve(address(royaltyModule), amount2);
royaltyModule.payRoyaltyOnBehalf(ipId2, testSender, address(StoryUSD), amount2);
IGraphAwareRoyaltyPolicy(royaltyPolicyLAPAddr).transferToVault(
ipId2,
newGroupId,
address(StoryUSD),
(amount2 * revShare) / royaltyModule.maxPercent()
);
IGraphAwareRoyaltyPolicy(royaltyPolicyLAPAddr).transferToVault(ipId2, newGroupId, address(StoryUSD));

address[] memory royaltyTokens = new address[](1);
royaltyTokens[0] = address(StoryUSD);
Expand Down
59 changes: 0 additions & 59 deletions test/integration/workflows/RoyaltyIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,69 +44,10 @@ contract RoyaltyIntegration is BaseIntegration {
super.run();
_beginBroadcast();
_setupTest();
_test_RoyaltyIntegration_transferToVaultAndClaimByTokenBatch();
_test_RoyaltyIntegration_claimAllRevenue();
_endBroadcast();
}

function _test_RoyaltyIntegration_transferToVaultAndClaimByTokenBatch()
private
logTest("test_RoyaltyIntegration_transferToVaultAndClaimByTokenBatch")
{
// setup IP graph
_setupIpGraph();

address[] memory childIpIds = new address[](3);
address[] memory royaltyPolicies = new address[](3);
address[] memory currencyTokens = new address[](3);
uint256[] memory amounts = new uint256[](3);

childIpIds[0] = childIpIdA;
royaltyPolicies[0] = royaltyPolicyLRPAddr;
currencyTokens[0] = address(StoryUSD);
amounts[0] = 10 ether;

childIpIds[1] = childIpIdB;
royaltyPolicies[1] = royaltyPolicyLRPAddr;
currencyTokens[1] = address(StoryUSD);
amounts[1] = 10 ether;

childIpIds[2] = grandChildIpId;
royaltyPolicies[2] = royaltyPolicyLRPAddr;
currencyTokens[2] = address(StoryUSD);
amounts[2] = 2 ether;

childIpIds[3] = childIpIdC;
royaltyPolicies[3] = royaltyPolicyLAPAddr;
currencyTokens[3] = address(StoryUSD);
amounts[3] = 10 ether;

uint256 claimerBalanceBefore = StoryUSD.balanceOf(ancestorIpId);

uint256[] memory amountsClaimed = royaltyWorkflows.transferToVaultAndClaimByTokenBatch({
ancestorIpId: ancestorIpId,
claimer: ancestorIpId,
childIpIds: childIpIds,
royaltyPolicies: royaltyPolicies,
currencyTokens: currencyTokens,
amounts: amounts
});

uint256 claimerBalanceAfter = StoryUSD.balanceOf(ancestorIpId);

assertEq(amountsClaimed.length, 1); // there is 1 currency token
assertEq(claimerBalanceAfter - claimerBalanceBefore, amountsClaimed[0]);
assertEq(
claimerBalanceAfter - claimerBalanceBefore,
defaultMintingFeeA +
defaultMintingFeeA + // 1000 + 1000 from minting fee of childIpA and childIpB
10 ether + // 10 currency tokens from childIpA transferred to vault
10 ether + // 10 currency tokens from childIpB transferred to vault
2 ether + // 2 currency tokens from grandChildIp transferred to vault
10 ether // 10 currency tokens from childIpC transferred to vault
);
}

function _test_RoyaltyIntegration_claimAllRevenue() private logTest("test_RoyaltyIntegration_claimAllRevenue") {
// setup IP graph
_setupIpGraph();
Expand Down
14 changes: 2 additions & 12 deletions test/workflows/GroupingWorkflows.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -339,25 +339,15 @@ contract GroupingWorkflowsTest is BaseTest {
vm.startPrank(ipOwner1);
mockToken.approve(address(royaltyModule), amount1);
royaltyModule.payRoyaltyOnBehalf(ipId1, ipOwner1, address(mockToken), amount1);
royaltyPolicyLAP.transferToVault(
ipId1,
newGroupId,
address(mockToken),
(amount1 * revShare) / royaltyModule.maxPercent()
);
royaltyPolicyLAP.transferToVault(ipId1, newGroupId, address(mockToken));
vm.stopPrank();

uint256 amount2 = 10_000 * 10 ** mockToken.decimals(); // 10,000 tokens
mockToken.mint(ipOwner2, amount2);
vm.startPrank(ipOwner2);
mockToken.approve(address(royaltyModule), amount2);
royaltyModule.payRoyaltyOnBehalf(ipId2, ipOwner2, address(mockToken), amount2);
royaltyPolicyLAP.transferToVault(
ipId2,
newGroupId,
address(mockToken),
(amount2 * revShare) / royaltyModule.maxPercent()
);
royaltyPolicyLAP.transferToVault(ipId2, newGroupId, address(mockToken));
vm.stopPrank();

address[] memory royaltyTokens = new address[](1);
Expand Down
60 changes: 0 additions & 60 deletions test/workflows/RoyaltyWorkflows.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,66 +42,6 @@ contract RoyaltyWorkflowsTest is BaseTest {
_setupCurrencyTokens();
}

function test_RoyaltyWorkflows_transferToVaultAndClaimByTokenBatch() public {
_setupIpGraph();

address[] memory childIpIds = new address[](4);
address[] memory royaltyPolicies = new address[](4);
address[] memory currencyTokens = new address[](4);
uint256[] memory amounts = new uint256[](4);

childIpIds[0] = childIpIdA;
royaltyPolicies[0] = address(royaltyPolicyLRP);
currencyTokens[0] = address(mockTokenA);
amounts[0] = 10 ether;

childIpIds[1] = childIpIdB;
royaltyPolicies[1] = address(royaltyPolicyLRP);
currencyTokens[1] = address(mockTokenA);
amounts[1] = 10 ether;

childIpIds[2] = grandChildIpId;
royaltyPolicies[2] = address(royaltyPolicyLRP);
currencyTokens[2] = address(mockTokenA);
amounts[2] = 1 ether;

childIpIds[3] = childIpIdC;
royaltyPolicies[3] = address(royaltyPolicyLAP);
currencyTokens[3] = address(mockTokenC);
amounts[3] = 10 ether;

uint256 claimerBalanceABefore = mockTokenA.balanceOf(ancestorIpId);
uint256 claimerBalanceCBefore = mockTokenC.balanceOf(ancestorIpId);

uint256[] memory amountsClaimed = royaltyWorkflows.transferToVaultAndClaimByTokenBatch({
ancestorIpId: ancestorIpId,
claimer: ancestorIpId,
childIpIds: childIpIds,
royaltyPolicies: royaltyPolicies,
currencyTokens: currencyTokens,
amounts: amounts
});

uint256 claimerBalanceAAfter = mockTokenA.balanceOf(ancestorIpId);
uint256 claimerBalanceCAfter = mockTokenC.balanceOf(ancestorIpId);

assertEq(amountsClaimed.length, 2); // there are 2 currency tokens
assertEq(claimerBalanceAAfter - claimerBalanceABefore, amountsClaimed[0]);
assertEq(claimerBalanceCAfter - claimerBalanceCBefore, amountsClaimed[1]);
assertEq(
claimerBalanceAAfter - claimerBalanceABefore,
defaultMintingFeeA +
defaultMintingFeeA + // 1000 + 1000 from minting fee of childIpA and childIpB
10 ether + // 10 currency tokens from childIpA transferred to vault
10 ether + // 10 currency tokens from childIpB transferred to vault
1 ether // 1 currency token from grandChildIp transferred to vault
);
assertEq(
claimerBalanceCAfter - claimerBalanceCBefore,
defaultMintingFeeC + 10 ether // 10 currency tokens from childIpC transferred to vault
);
}

function test_RoyaltyWorkflows_claimAllRevenue() public {
_setupIpGraph();

Expand Down
32 changes: 16 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@

"@story-protocol/protocol-core@github:storyprotocol/protocol-core-v1#main":
version "1.1.0"
resolved "https://codeload.github.com/storyprotocol/protocol-core-v1/tar.gz/ed12aec4bfea9127234873dcf06f9f914db068ab"
resolved "https://codeload.github.com/storyprotocol/protocol-core-v1/tar.gz/bd1d8ce8da09c6ea66159c11f9abc4d36fd4f25b"
dependencies:
"@openzeppelin/contracts" "5.0.2"
"@openzeppelin/contracts-upgradeable" "5.0.2"
Expand Down Expand Up @@ -504,9 +504,9 @@
integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==

"@ungap/structured-clone@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
version "1.2.1"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.1.tgz#28fa185f67daaf7b7a1a8c1d445132c5d979f8bd"
integrity sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==

abbrev@1:
version "1.1.1"
Expand Down Expand Up @@ -888,9 +888,9 @@ death@^1.1.0:
integrity sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==

debug@^4.3.1, debug@^4.3.2, debug@^4.3.5:
version "4.3.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
version "4.4.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
dependencies:
ms "^2.1.3"

Expand Down Expand Up @@ -958,9 +958,9 @@ doctrine@^3.0.0:
esutils "^2.0.2"

dotenv@^16.4.1:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==
version "16.4.7"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==

[email protected]:
version "6.5.4"
Expand Down Expand Up @@ -2084,9 +2084,9 @@ prettier@^2.3.1, prettier@^2.8.3:
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==

prettier@^3.0.0:
version "3.4.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.1.tgz#e211d451d6452db0a291672ca9154bc8c2579f7b"
integrity sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==
version "3.4.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f"
integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==

proto-list@~1.2.1:
version "1.2.4"
Expand Down Expand Up @@ -2468,9 +2468,9 @@ table-layout@^1.0.2:
wordwrapjs "^4.0.0"

table@^6.8.1:
version "6.8.2"
resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58"
integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==
version "6.9.0"
resolved "https://registry.yarnpkg.com/table/-/table-6.9.0.tgz#50040afa6264141c7566b3b81d4d82c47a8668f5"
integrity sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==
dependencies:
ajv "^8.0.1"
lodash.truncate "^4.4.2"
Expand Down

0 comments on commit f4d1823

Please sign in to comment.