Skip to content

Commit f40ad0c

Browse files
authored
feat(grouping): auto vault deployment (storyprotocol#445)
1 parent d5a6a87 commit f40ad0c

File tree

2 files changed

+97
-0
lines changed

2 files changed

+97
-0
lines changed

contracts/modules/grouping/GroupingModule.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ contract GroupingModule is
282282
if (!ROYALTY_MODULE.isWhitelistedRoyaltyToken(token)) {
283283
revert Errors.GroupingModule__RoyaltyTokenNotWhitelisted(groupId, token);
284284
}
285+
// deploy vault for each group member if not already deployed
286+
for (uint256 i = 0; i < ipIds.length; i++) {
287+
if (ROYALTY_MODULE.ipRoyaltyVaults(ipIds[i]) == address(0)) ROYALTY_MODULE.deployVault(ipIds[i]);
288+
}
285289
// trigger group pool to distribute rewards to group members vault
286290
uint256[] memory rewards = pool.distributeRewards(groupId, token, ipIds);
287291
emit ClaimedReward(groupId, token, ipIds, rewards);

test/foundry/modules/grouping/GroupingModule.t.sol

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,99 @@ contract GroupingModuleTest is BaseTest, ERC721Holder {
633633
assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId1)), 50);
634634
}
635635

636+
function test_GroupingModule_claimReward_memberVaultsNotDeployed() public {
637+
vm.warp(100);
638+
vm.prank(alice);
639+
address groupId = groupingModule.registerGroup(address(rewardPool));
640+
641+
uint256 termsId = pilTemplate.registerLicenseTerms(
642+
PILFlavors.commercialRemix({
643+
mintingFee: 0,
644+
commercialRevShare: 10_000_000,
645+
currencyToken: address(erc20),
646+
royaltyPolicy: address(royaltyPolicyLRP)
647+
})
648+
);
649+
650+
Licensing.LicensingConfig memory licensingConfig = Licensing.LicensingConfig({
651+
isSet: true,
652+
mintingFee: 0,
653+
licensingHook: address(0),
654+
hookData: "",
655+
commercialRevShare: 10 * 10 ** 6,
656+
disabled: false,
657+
expectMinimumGroupRewardShare: 10 * 10 ** 6,
658+
expectGroupRewardPool: address(evenSplitGroupPool)
659+
});
660+
661+
vm.startPrank(ipOwner1);
662+
licensingModule.attachLicenseTerms(ipId1, address(pilTemplate), termsId);
663+
licensingModule.setLicensingConfig(ipId1, address(pilTemplate), termsId, licensingConfig);
664+
assertEq(royaltyModule.ipRoyaltyVaults(ipId1), address(0)); // confirm the vault is not deployed
665+
vm.stopPrank();
666+
vm.startPrank(ipOwner2);
667+
licensingModule.attachLicenseTerms(ipId2, address(pilTemplate), termsId);
668+
licensingModule.setLicensingConfig(ipId2, address(pilTemplate), termsId, licensingConfig);
669+
assertEq(royaltyModule.ipRoyaltyVaults(ipId2), address(0)); // confirm the vault is not deployed
670+
vm.stopPrank();
671+
vm.startPrank(ipOwner5);
672+
licensingModule.attachLicenseTerms(ipId5, address(pilTemplate), termsId);
673+
licensingModule.setLicensingConfig(ipId5, address(pilTemplate), termsId, licensingConfig);
674+
assertEq(royaltyModule.ipRoyaltyVaults(ipId5), address(0)); // confirm the vault is not deployed
675+
vm.stopPrank();
676+
677+
licensingConfig.expectGroupRewardPool = address(0);
678+
vm.startPrank(alice);
679+
licensingModule.attachLicenseTerms(groupId, address(pilTemplate), termsId);
680+
licensingModule.setLicensingConfig(groupId, address(pilTemplate), termsId, licensingConfig);
681+
address[] memory ipIds = new address[](3);
682+
ipIds[0] = ipId1;
683+
ipIds[1] = ipId2;
684+
ipIds[2] = ipId5;
685+
groupingModule.addIp(groupId, ipIds, 100e6);
686+
assertEq(ipAssetRegistry.totalMembers(groupId), 3);
687+
assertEq(rewardPool.getTotalIps(groupId), 3);
688+
vm.stopPrank();
689+
690+
address[] memory parentIpIds = new address[](1);
691+
parentIpIds[0] = groupId;
692+
uint256[] memory licenseTermsIds = new uint256[](1);
693+
licenseTermsIds[0] = termsId;
694+
vm.prank(ipOwner3);
695+
licensingModule.registerDerivative(ipId3, parentIpIds, licenseTermsIds, address(pilTemplate), "", 0, 100e6, 0);
696+
697+
erc20.mint(ipOwner3, 1000);
698+
vm.startPrank(ipOwner3);
699+
erc20.approve(address(royaltyModule), 1000);
700+
royaltyModule.payRoyaltyOnBehalf(ipId3, ipOwner3, address(erc20), 1000);
701+
vm.stopPrank();
702+
royaltyPolicyLRP.transferToVault(ipId3, groupId, address(erc20));
703+
vm.warp(vm.getBlockTimestamp() + 7 days);
704+
705+
vm.expectEmit();
706+
emit IGroupingModule.CollectedRoyaltiesToGroupPool(groupId, address(erc20), address(rewardPool), 100);
707+
groupingModule.collectRoyalties(groupId, address(erc20));
708+
709+
address[] memory claimIpIds = new address[](3);
710+
claimIpIds[0] = ipId1;
711+
claimIpIds[1] = ipId2;
712+
claimIpIds[2] = ipId5;
713+
714+
// claim amount = royalties collected / # member IPs in the group = 100 / 3 = 33
715+
uint256[] memory claimAmounts = new uint256[](3);
716+
claimAmounts[0] = 33;
717+
claimAmounts[1] = 33;
718+
claimAmounts[2] = 33;
719+
720+
vm.expectEmit();
721+
emit IGroupingModule.ClaimedReward(groupId, address(erc20), claimIpIds, claimAmounts);
722+
groupingModule.claimReward(groupId, address(erc20), claimIpIds);
723+
assertEq(erc20.balanceOf(address(rewardPool)), 1);
724+
assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId1)), 33);
725+
assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId2)), 33);
726+
assertEq(erc20.balanceOf(royaltyModule.ipRoyaltyVaults(ipId5)), 33);
727+
}
728+
636729
function test_GroupingModule_claimReward_revert_notWhitelistedPool() public {
637730
vm.warp(100);
638731
vm.prank(alice);

0 commit comments

Comments
 (0)