@@ -7,6 +7,7 @@ import { ERC165Checker } from "@openzeppelin/contracts/utils/introspection/ERC16
7
7
import { MulticallUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol " ;
8
8
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol " ;
9
9
10
+ import { Errors as CoreErrors } from "@storyprotocol/core/lib/Errors.sol " ;
10
11
// solhint-disable-next-line max-line-length
11
12
import { IGraphAwareRoyaltyPolicy } from "@storyprotocol/core/interfaces/modules/royalty/policies/IGraphAwareRoyaltyPolicy.sol " ;
12
13
import { IIpRoyaltyVault } from "@storyprotocol/core/interfaces/modules/royalty/policies/IIpRoyaltyVault.sol " ;
@@ -45,15 +46,13 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
45
46
/// and claims revenue on that snapshot for each specified currency token.
46
47
/// @param ancestorIpId The address of the ancestor IP.
47
48
/// @param claimer The address of the claimer of the revenue tokens (must be a royalty token holder).
48
- /// @param currencyTokens The addresses of the currency (revenue) tokens to claim (each address must be unique).
49
49
/// @param royaltyClaimDetails The details of the royalty claim from child IPs,
50
50
/// see {IRoyaltyWorkflows-RoyaltyClaimDetails}.
51
51
/// @return snapshotId The ID of the snapshot taken.
52
52
/// @return amountsClaimed The amount of revenue claimed for each currency token.
53
53
function transferToVaultAndSnapshotAndClaimByTokenBatch (
54
54
address ancestorIpId ,
55
55
address claimer ,
56
- address [] calldata currencyTokens ,
57
56
RoyaltyClaimDetails[] calldata royaltyClaimDetails
58
57
) external returns (uint256 snapshotId , uint256 [] memory amountsClaimed ) {
59
58
// Transfers to ancestor's vault an amount of revenue tokens claimable via the given royalty policy
@@ -75,7 +74,7 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
75
74
// Claims revenue for each specified currency token from the latest snapshot
76
75
amountsClaimed = ancestorIpRoyaltyVault.claimRevenueOnBehalfByTokenBatch ({
77
76
snapshotId: snapshotId,
78
- tokenList: currencyTokens ,
77
+ tokenList: _getCurrencyTokenList (royaltyClaimDetails) ,
79
78
claimer: claimer
80
79
});
81
80
}
@@ -84,7 +83,6 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
84
83
/// specified currency token both on the new snapshot and on each specified unclaimed snapshots.
85
84
/// @param ancestorIpId The address of the ancestor IP.
86
85
/// @param claimer The address of the claimer of the revenue tokens (must be a royalty token holder).
87
- /// @param currencyTokens The addresses of the currency (revenue) tokens to claim (each address must be unique).
88
86
/// @param unclaimedSnapshotIds The IDs of unclaimed snapshots to include in the claim.
89
87
/// @param royaltyClaimDetails The details of the royalty claim from child IPs,
90
88
/// see {IRoyaltyWorkflows-RoyaltyClaimDetails}.
@@ -93,7 +91,6 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
93
91
function transferToVaultAndSnapshotAndClaimBySnapshotBatch (
94
92
address ancestorIpId ,
95
93
address claimer ,
96
- address [] calldata currencyTokens ,
97
94
uint256 [] calldata unclaimedSnapshotIds ,
98
95
RoyaltyClaimDetails[] calldata royaltyClaimDetails
99
96
) external returns (uint256 snapshotId , uint256 [] memory amountsClaimed ) {
@@ -113,6 +110,8 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
113
110
// Takes a snapshot of the ancestor IP's royalty vault
114
111
snapshotId = ancestorIpRoyaltyVault.snapshot ();
115
112
113
+ address [] memory currencyTokens = _getCurrencyTokenList (royaltyClaimDetails);
114
+
116
115
// Claims revenue for each specified currency token from the latest snapshot
117
116
amountsClaimed = ancestorIpRoyaltyVault.claimRevenueOnBehalfByTokenBatch ({
118
117
snapshotId: snapshotId,
@@ -130,8 +129,13 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
130
129
})
131
130
returns (uint256 claimedAmount ) {
132
131
amountsClaimed[i] += claimedAmount;
133
- } catch {
134
- amountsClaimed[i] += 0 ;
132
+ } catch (bytes memory reason ) {
133
+ // If the error is not IpRoyaltyVault__NoClaimableTokens, revert with the original error
134
+ if (CoreErrors.IpRoyaltyVault__NoClaimableTokens.selector != bytes4 (reason)) {
135
+ assembly {
136
+ revert (add (reason, 32 ), mload (reason))
137
+ }
138
+ }
135
139
}
136
140
}
137
141
}
@@ -195,13 +199,54 @@ contract RoyaltyWorkflows is IRoyaltyWorkflows, MulticallUpgradeable, AccessMana
195
199
})
196
200
returns (uint256 claimedAmount ) {
197
201
amountsClaimed[i] += claimedAmount;
198
- } catch {
199
- // Continue to the next currency token
200
- amountsClaimed[i] += 0 ;
202
+ } catch (bytes memory reason ) {
203
+ // If the error is not IpRoyaltyVault__NoClaimableTokens, revert with the original error
204
+ if (CoreErrors.IpRoyaltyVault__NoClaimableTokens.selector != bytes4 (reason)) {
205
+ assembly {
206
+ revert (add (reason, 32 ), mload (reason))
207
+ }
208
+ }
201
209
}
202
210
}
203
211
}
204
212
213
+ /// @dev Extracts all unique currency token addresses from an array of RoyaltyClaimDetails.
214
+ /// @param royaltyClaimDetails The details of the royalty claim from child IPs,
215
+ /// see {IRoyaltyWorkflows-RoyaltyClaimDetails}.
216
+ /// @return currencyTokenList An array of unique currency token addresses extracted from `royaltyClaimDetails`.
217
+ function _getCurrencyTokenList (
218
+ RoyaltyClaimDetails[] calldata royaltyClaimDetails
219
+ ) private pure returns (address [] memory currencyTokenList ) {
220
+ uint256 length = royaltyClaimDetails.length ;
221
+ address [] memory tempUniqueTokenList = new address [](length);
222
+ uint256 uniqueCount = 0 ;
223
+
224
+ for (uint256 i = 0 ; i < length; i++ ) {
225
+ address currencyToken = royaltyClaimDetails[i].currencyToken;
226
+ bool isDuplicate = false ;
227
+
228
+ // Check if `currencyToken` already in `tempUniqueTokenList`
229
+ for (uint256 j = 0 ; j < uniqueCount; j++ ) {
230
+ if (tempUniqueTokenList[j] == currencyToken) {
231
+ // set the `isDuplicate` flag if `currencyToken` already in `tempUniqueTokenList`
232
+ isDuplicate = true ;
233
+ break ;
234
+ }
235
+ }
236
+
237
+ // Add `currencyToken` to `tempUniqueTokenList` if it's not already in `tempUniqueTokenList`
238
+ if (! isDuplicate) {
239
+ tempUniqueTokenList[uniqueCount] = currencyToken;
240
+ uniqueCount++ ;
241
+ }
242
+ }
243
+
244
+ currencyTokenList = new address [](uniqueCount);
245
+ for (uint256 i = 0 ; i < uniqueCount; i++ ) {
246
+ currencyTokenList[i] = tempUniqueTokenList[i];
247
+ }
248
+ }
249
+
205
250
//
206
251
// Upgrade
207
252
//
0 commit comments