Skip to content

Commit

Permalink
Add e2e tests for grouping module (#345)
Browse files Browse the repository at this point in the history
* test: Add e2e tests for grouping module

* chore: Update group.royalty.test.ts
  • Loading branch information
tyitang authored Dec 16, 2024
1 parent 34c5f2b commit 286bedc
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 4 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ DEVNET_URL = http://
DEVNET_CHAINID = 1315
DEVNET_PRIVATEKEY =
DEVNET_USER1 =
DEVNET_USER2 =
DEVNET_ERC721 =
3 changes: 2 additions & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const DEVNET_URL = process.env.DEVNET_URL || "http://"
const DEVNET_CHAINID = Number(process.env.DEVNET_CHAINID) || 1513
const DEVNET_PRIVATEKEY = process.env.DEVNET_PRIVATEKEY || "0xkey"
const DEVNET_USER1 = process.env.DEVNET_USER1 || "0xkey"
const DEVNET_USER2 = process.env.DEVNET_USER2 || "0xkey"

if (USE_TENDERLY) {
tdly.setup({
Expand Down Expand Up @@ -71,7 +72,7 @@ const config: HardhatUserConfig = {
odyssey: {
chainId: DEVNET_CHAINID,
url: DEVNET_URL,
accounts: [DEVNET_PRIVATEKEY, DEVNET_USER1],
accounts: [DEVNET_PRIVATEKEY, DEVNET_USER1, DEVNET_USER2],
},
localhost: {
chainId: 31337,
Expand Down
17 changes: 17 additions & 0 deletions test/hardhat/e2e/grouping/group.authority.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Test: Group Authorization

import { EvenSplitGroupPool } from "../constants";
import "../setup"
import { expect } from "chai"

describe("Grouping Module Authorization", function () {
it("Non-admin whitelist group reward pool", async function () {
await expect(
this.groupingModule.connect(this.user1).whitelistGroupRewardPool(EvenSplitGroupPool, false)
).to.be.rejectedWith(Error);

const isWhitelisted = await this.ipAssetRegistry.isWhitelistedGroupRewardPool(EvenSplitGroupPool);
expect(isWhitelisted).to.be.true;
});
});

118 changes: 117 additions & 1 deletion test/hardhat/e2e/grouping/group.ipa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ describe("Add/Remove IP from Group IPA", function () {
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
await expect(
this.groupingModule.connect(this.user1).addIp(groupId, [ipId])
).to.be.revertedWithCustomError(this.errors, "AccessController__PermissionDenied");;
).to.be.revertedWithCustomError(this.errors, "AccessController__PermissionDenied");

const containsIp = await this.ipAssetRegistry.containsIp(groupId, ipId);
expect(containsIp).to.be.false;
Expand Down Expand Up @@ -147,3 +147,119 @@ describe("Add/Remove IP from Group IPA", function () {
).to.be.revertedWithCustomError(this.errors, "LicenseRegistry__IpHasNoGroupLicenseTerms");
});
});

describe("Group is locked due to registered derivative", function () {
let groupId: any;
let commRemixTermsId: any;
let ipId1: any;
let ipId2: any;

before(async function () {
groupId = await expect(
this.groupingModule.registerGroup(EvenSplitGroupPool)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait()).then((receipt) => receipt.logs[5].args[0]);
console.log("groupId", groupId);

commRemixTermsId = await registerPILTerms(true, 0, 10 * 10 ** 6, RoyaltyPolicyLRP);
await expect(
this.licensingModule.attachLicenseTerms(groupId, PILicenseTemplate, commRemixTermsId)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Register IP
console.log("============ Register IP1 ============");
({ ipId: ipId1 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId, this.user1, this.user1));
await expect(
this.licensingModule.connect(this.user1).setLicensingConfig(ipId1, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Add IP to the group
console.log("============ Add Ips to group ============");
await expect(
this.groupingModule.addIp(groupId, [ipId1])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
expect(
await this.evenSplitGroupPool.getTotalIps(groupId)
).to.be.equal(1);

// Register derivative IP
console.log("============ Register IP2 ============");
({ ipId: ipId2 } = await mintNFTAndRegisterIPA(this.user2, this.user2));
await expect(
this.licensingModule.connect(this.user2).registerDerivative(ipId2, [groupId], [commRemixTermsId], PILicenseTemplate, "0x", 0, 100e6)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
});

it("Add Ip to locked group", async function () {
const { ipId } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId);
await expect(
this.licensingModule.setLicensingConfig(ipId, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

await expect(
this.groupingModule.addIp(groupId, [ipId])
).to.be.revertedWithCustomError(this.errors, "GroupingModule__GroupFrozenDueToHasDerivativeIps");
});

it("Remove Ip from locked group", async function () {
await expect(
this.groupingModule.removeIp(groupId, [ipId1])
).to.be.revertedWithCustomError(this.errors, "GroupingModule__GroupFrozenDueToHasDerivativeIps");
});
});

describe("Group is locked due to minted license token", function () {
let groupId: any;
let commRemixTermsId: any;
let ipId1: any;

before(async function () {
groupId = await expect(
this.groupingModule.registerGroup(EvenSplitGroupPool)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait()).then((receipt) => receipt.logs[5].args[0]);
console.log("groupId", groupId);

commRemixTermsId = await registerPILTerms(true, 0, 10 * 10 ** 6, RoyaltyPolicyLRP);
await expect(
this.licensingModule.attachLicenseTerms(groupId, PILicenseTemplate, commRemixTermsId)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Register IP
console.log("============ Register IP1 ============");
({ ipId: ipId1 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId, this.user1, this.user1));
await expect(
this.licensingModule.connect(this.user1).setLicensingConfig(ipId1, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Add IP to the group
console.log("============ Add Ips to group ============");
await expect(
this.groupingModule.addIp(groupId, [ipId1])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
expect(
await this.evenSplitGroupPool.getTotalIps(groupId)
).to.be.equal(1);

// Mint license token
console.log("============ Group mint license token ============");
await expect(
this.licensingModule.mintLicenseTokens(groupId, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
});

it("Add Ip to locked group", async function () {
const { ipId } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId);
await expect(
this.licensingModule.setLicensingConfig(ipId, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

await expect(
this.groupingModule.addIp(groupId, [ipId])
).to.be.revertedWithCustomError(this.errors, "GroupingModule__GroupFrozenDueToAlreadyMintLicenseTokens");
});

it("Remove Ip from locked group", async function () {
await expect(
this.groupingModule.removeIp(groupId, [ipId1])
).to.be.revertedWithCustomError(this.errors, "GroupingModule__GroupFrozenDueToAlreadyMintLicenseTokens");
});
});
229 changes: 229 additions & 0 deletions test/hardhat/e2e/grouping/group.royalty.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// Test: Group IP Asset Royalty Distribution

import "../setup"
import { expect } from "chai"
import { EvenSplitGroupPool, MockERC20, PILicenseTemplate, RoyaltyPolicyLAP } from "../constants"
import { LicensingConfig, registerPILTerms } from "../utils/licenseHelper";
import { mintNFTAndRegisterIPA, mintNFTAndRegisterIPAWithLicenseTerms } from "../utils/mintNFTAndRegisterIPA";
import { getErc20Balance } from "../utils/erc20Helper";

describe("Group IP Asset Royalty Distribution", function () {
let groupId: any;
let commRemixTermsId: any;
let ipId1: any;
let ipId2: any;

let rewardPoolBalanceBefore: any;
let ip1BalanceBefore: any;
let ip2BalanceBefore: any;

before(async function () {
console.log("============ Register Group ============");
groupId = await expect(
this.groupingModule.registerGroup(EvenSplitGroupPool)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait()).then((receipt) => receipt.logs[5].args[0]);
console.log("groupId", groupId);

console.log("============ Register Lisence Terms ============");
commRemixTermsId = await registerPILTerms(true, 0, 10 * 10 ** 6, RoyaltyPolicyLAP);
await expect(
this.licensingModule.attachLicenseTerms(groupId, PILicenseTemplate, commRemixTermsId)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Register IP
console.log("============ Register IP1 ============");
({ ipId: ipId1 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId, this.user1, this.user1));
await expect(
this.licensingModule.connect(this.user1).setLicensingConfig(ipId1, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

console.log("============ Register IP2 ============");
({ ipId: ipId2 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId, this.user2, this.user2));
await expect(
this.licensingModule.connect(this.user2).setLicensingConfig(ipId2, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Add IP to the group
console.log("============ Add IPs to group ============");
await expect(
this.groupingModule.addIp(groupId, [ipId1, ipId2])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

expect(
await this.evenSplitGroupPool.getTotalIps(groupId)
).to.be.equal(2);
});

it("Group royalties even split by member IPs", async function () {
// Register drivative IP
console.log("============ Register Derivative IP3 ============");
const {ipId: ipId3} = await mintNFTAndRegisterIPA();
await expect(
this.licensingModule.registerDerivative(ipId3, [groupId], [commRemixTermsId], PILicenseTemplate, "0x", 0, 100e6)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

rewardPoolBalanceBefore = await getErc20Balance(EvenSplitGroupPool);

// Pay royalty to IP3
console.log("============ Pay rayalty to IP3 ============");
await expect(
this.royaltyModule.payRoyaltyOnBehalf(ipId3, ipId3, MockERC20, 1000)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// console.log("============ Transfer to vault ============");
await expect(
this.royaltyPolicyLAP.transferToVault(ipId3, groupId, MockERC20)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Collect royalty
console.log("============ Collect royalty ============");
await expect(
this.groupingModule.collectRoyalties(groupId, MockERC20)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Check reward pool balance after royalty collection
expect(
await getErc20Balance(EvenSplitGroupPool)
).to.be.equal(rewardPoolBalanceBefore + 100n);

// Get claimable
console.log("============ Get claimable ============");
const claimableIp1 = await expect(
this.groupingModule.connect(this.user1).getClaimableReward(groupId, MockERC20, [ipId1])
).not.to.be.rejectedWith(Error);
console.log("IP1 claimable", claimableIp1);
const claimableIp2 = await expect(
this.groupingModule.connect(this.user2).getClaimableReward(groupId, MockERC20, [ipId2])
).not.to.be.rejectedWith(Error);
console.log("IP2 claimable", claimableIp2);

// Mint license token to trigger vault creation
console.log("============ Mint license token ============");
await expect(
this.licensingModule.mintLicenseTokens(ipId1, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
await expect(
this.licensingModule.mintLicenseTokens(ipId2, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
const vaultIp1 = await this.royaltyModule.ipRoyaltyVaults(ipId1);
console.log("vaultIp1", vaultIp1);
const vaultIp2 = await this.royaltyModule.ipRoyaltyVaults(ipId2);
console.log("vaultIp2", vaultIp2);

ip1BalanceBefore = await getErc20Balance(vaultIp1);
ip2BalanceBefore = await getErc20Balance(vaultIp2);

console.log("============ IP1 claim rewards ============");
await expect(
this.groupingModule.connect(this.user1).claimReward(groupId, MockERC20, [ipId1])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

console.log("============ IP2 claim rewards ============");
await expect(
this.groupingModule.connect(this.user2).claimReward(groupId, MockERC20, [ipId2])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

console.log("============ Check the balance after claim rewards ============");
const rewardPoolBalance = await getErc20Balance(EvenSplitGroupPool);
const ip1Balance = await getErc20Balance(vaultIp1);
const ip2Balance = await getErc20Balance(vaultIp2);
expect(rewardPoolBalance).to.be.equal(rewardPoolBalanceBefore);
expect(ip1Balance).to.be.equal(ip1BalanceBefore + 50n);
expect(ip2Balance).to.be.equal(ip2BalanceBefore + 50n);
});
});

describe("Non-Owner/Member Claim Group Royalty", function () {
let groupId: any;
let commRemixTermsId: any;
let ipId1: any;
let ipId2: any;

before(async function () {
console.log("============ Register Group ============");
groupId = await expect(
this.groupingModule.registerGroup(EvenSplitGroupPool)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait()).then((receipt) => receipt.logs[5].args[0]);
console.log("groupId", groupId);

console.log("============ Register Lisence Terms ============");
commRemixTermsId = await registerPILTerms(true, 0, 10 * 10 ** 6, RoyaltyPolicyLAP);
await expect(
this.licensingModule.attachLicenseTerms(groupId, PILicenseTemplate, commRemixTermsId)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Register IP
console.log("============ Register IP1 ============");
({ ipId: ipId1 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId));
await expect(
this.licensingModule.setLicensingConfig(ipId1, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

console.log("============ Register IP2 ============");
({ ipId: ipId2 } = await mintNFTAndRegisterIPAWithLicenseTerms(commRemixTermsId, this.user2, this.user2));
await expect(
this.licensingModule.connect(this.user2).setLicensingConfig(ipId2, PILicenseTemplate, commRemixTermsId, LicensingConfig)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Add IP to the group
console.log("============ Add IPs to group ============");
await expect(
this.groupingModule.addIp(groupId, [ipId1, ipId2])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

expect(
await this.evenSplitGroupPool.getTotalIps(groupId)
).to.be.equal(2);

// Mint license token
console.log("============ Mint license token ============");
await expect(
this.licensingModule.mintLicenseTokens(groupId, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
await expect(
this.licensingModule.mintLicenseTokens(ipId1, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
await expect(
this.licensingModule.mintLicenseTokens(ipId2, PILicenseTemplate, commRemixTermsId, 1, this.owner.address, "0x", 0)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
});

it("Non-Owner/Member collects group royalties", async function () {
// Pay royalty
console.log("============ Pay royalty to group ============");
await expect(
this.royaltyModule.payRoyaltyOnBehalf(groupId, this.owner.address, MockERC20, 100)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

const rewardPoolBalanceBefore = await getErc20Balance(EvenSplitGroupPool);

console.log("============ Collect royalty ============");
await expect(
this.groupingModule.connect(this.user1).collectRoyalties(groupId, MockERC20)
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());

// Check reward pool balance after royalty collection
expect(
await getErc20Balance(EvenSplitGroupPool)
).to.be.equal(rewardPoolBalanceBefore + 100n);

const vaultIp1 = await this.royaltyModule.ipRoyaltyVaults(ipId1);
const vaultIp2 = await this.royaltyModule.ipRoyaltyVaults(ipId2);
const ip1BalanceBefore = await getErc20Balance(vaultIp1);
const ip2BalanceBefore = await getErc20Balance(vaultIp2);

console.log("============ Claim rewards ============");
await expect(
this.groupingModule.connect(this.user1).claimReward(groupId, MockERC20, [ipId1, ipId2])
).not.to.be.rejectedWith(Error).then((tx) => tx.wait());
expect(
await getErc20Balance(EvenSplitGroupPool)
).to.be.equal(rewardPoolBalanceBefore);
expect(
await getErc20Balance(vaultIp1)
).to.be.equal(ip1BalanceBefore + 50n);
expect(
await getErc20Balance(vaultIp2)
).to.be.equal(ip2BalanceBefore + 50n);
});
});
Loading

0 comments on commit 286bedc

Please sign in to comment.