UNPKG

@vechain/vebetterdao-contracts

Version:

Open-source repository that houses the smart contracts powering the decentralized VeBetterDAO on the VeChain Thor blockchain.

708 lines (707 loc) 55.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const upgrades_core_1 = require("@openzeppelin/upgrades-core"); const local_1 = require("@repo/config/contracts/envs/local"); const chai_1 = require("chai"); const hardhat_1 = require("hardhat"); const mocha_1 = require("mocha"); const helpers_1 = require("../../scripts/helpers"); const helpers_2 = require("../helpers"); const xnodes_1 = require("../helpers/xnodes"); (0, mocha_1.describe)("Contract upgradeablity @shard15e", () => { // We prepare the environment for 4 creators let creator1; let creator2; let creator3; let creator4; before(async function () { const { creators } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true }); creator1 = creators[0]; creator2 = creators[1]; creator3 = creators[2]; creator4 = creators[3]; }); (0, mocha_1.it)("User with UPGRADER_ROLE should be able to upgrade the contract", async function () { const { x2EarnApps, owner, administrationUtils, endorsementUtils, voteEligibilityUtils, appStorageUtils } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("X2EarnApps", { libraries: { AdministrationUtils: await administrationUtils.getAddress(), EndorsementUtils: await endorsementUtils.getAddress(), VoteEligibilityUtils: await voteEligibilityUtils.getAddress(), AppStorageUtils: await appStorageUtils.getAddress(), }, }); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnApps.getAddress()); const UPGRADER_ROLE = await x2EarnApps.UPGRADER_ROLE(); (0, chai_1.expect)(await x2EarnApps.hasRole(UPGRADER_ROLE, owner.address)).to.eql(true); await (0, chai_1.expect)(x2EarnApps.connect(owner).upgradeToAndCall(await implementation.getAddress(), "0x")).to.not.be.reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnApps.getAddress()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.not.eql(currentImplAddress.toUpperCase()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.eql((await implementation.getAddress()).toUpperCase()); }); (0, mocha_1.it)("Only user with UPGRADER_ROLE should be able to upgrade the contract", async function () { const { x2EarnApps, otherAccount, administrationUtils, endorsementUtils, voteEligibilityUtils, appStorageUtils } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("X2EarnApps", { libraries: { AdministrationUtils: await administrationUtils.getAddress(), EndorsementUtils: await endorsementUtils.getAddress(), VoteEligibilityUtils: await voteEligibilityUtils.getAddress(), AppStorageUtils: await appStorageUtils.getAddress(), }, }); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnApps.getAddress()); const UPGRADER_ROLE = await x2EarnApps.UPGRADER_ROLE(); (0, chai_1.expect)(await x2EarnApps.hasRole(UPGRADER_ROLE, otherAccount.address)).to.eql(false); await (0, chai_1.expect)(x2EarnApps.connect(otherAccount).upgradeToAndCall(await implementation.getAddress(), "0x")).to.be .reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnApps.getAddress()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.eql(currentImplAddress.toUpperCase()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.not.eql((await implementation.getAddress()).toUpperCase()); }); (0, mocha_1.it)("X2Earn Apps Info added pre contract upgrade should should be same after upgrade", async () => { const config = (0, local_1.createLocalConfig)(); config.EMISSIONS_CYCLE_DURATION = 24; config.X2EARN_NODE_COOLDOWN_PERIOD = 1; const { timeLock, owner, otherAccounts, vechainNodesMock, veBetterPassport, administrationUtils, endorsementUtils, voteEligibilityUtils, appStorageUtils, x2EarnRewardsPool, x2EarnCreator, stargateNftMock, administrationUtilsV2, endorsementUtilsV2, voteEligibilityUtilsV2, administrationUtilsV3, endorsementUtilsV3, voteEligibilityUtilsV3, xAllocationVoting, administrationUtilsV4, endorsementUtilsV4, voteEligibilityUtilsV4, administrationUtilsV5, endorsementUtilsV5, voteEligibilityUtilsV5, administrationUtilsV6, endorsementUtilsV6, voteEligibilityUtilsV6, administrationUtilsV7, endorsementUtilsV7, voteEligibilityUtilsV7, } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy X2EarnApps const x2EarnAppsV1 = (await (0, helpers_1.deployProxy)("X2EarnAppsV1", [ "ipfs://", [await timeLock.getAddress(), owner.address], owner.address, owner.address, ])); // Add app 1 await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[2].address, otherAccounts[2].address, "My app", "metadataURI"); // Add app 2 await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[3].address, otherAccounts[3].address, "My app #2", "metadataURI"); // start round using V1 contract await (0, helpers_2.startNewAllocationRound)(); // Add app 3 during first round await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[4].address, otherAccounts[4].address, "My app #3", "metadataURI"); const appsV1 = await x2EarnAppsV1.apps(); // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Upgrade X2EarnAppsV1 to X2EarnApps const x2EarnAppsV2 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV1", "X2EarnAppsV2", await x2EarnAppsV1.getAddress(), [ config.XAPP_GRACE_PERIOD, await vechainNodesMock.getAddress(), await veBetterPassport.getAddress(), await x2EarnCreator.getAddress(), ], { version: 2, libraries: { AdministrationUtilsV2: await administrationUtilsV2.getAddress(), EndorsementUtilsV2: await endorsementUtilsV2.getAddress(), VoteEligibilityUtilsV2: await voteEligibilityUtilsV2.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV2 = await x2EarnAppsV2.apps(); (0, chai_1.expect)(appsV1).to.eql(appsV2); // Upgrade X2EarnAppsV2 to X2EarnApps const x2EarnAppsV3 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV2", "X2EarnAppsV3", await x2EarnAppsV2.getAddress(), [config.X2EARN_NODE_COOLDOWN_PERIOD, await xAllocationVoting.getAddress()], { version: 3, libraries: { AdministrationUtilsV3: await administrationUtilsV3.getAddress(), EndorsementUtilsV3: await endorsementUtilsV3.getAddress(), VoteEligibilityUtilsV3: await voteEligibilityUtilsV3.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV3 = await x2EarnAppsV3.apps(); (0, chai_1.expect)(appsV2).to.eql(appsV3); const cooldownPeriod = await x2EarnAppsV3.cooldownPeriod(); (0, chai_1.expect)(cooldownPeriod).to.eql(1n); // Upgrade X2EarnAppsV2 to X2EarnApps const x2EarnAppsV4 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV3", "X2EarnAppsV4", await x2EarnAppsV3.getAddress(), [await x2EarnRewardsPool.getAddress()], { version: 4, libraries: { AdministrationUtilsV4: await administrationUtilsV4.getAddress(), EndorsementUtilsV4: await endorsementUtilsV4.getAddress(), VoteEligibilityUtilsV4: await voteEligibilityUtilsV4.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV4 = await x2EarnAppsV4.apps(); (0, chai_1.expect)(appsV3).to.eql(appsV4); // Upgrade X2EarnAppsV4 to X2EarnAppsV5 const x2EarnAppsV5 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV4", "X2EarnAppsV5", await x2EarnAppsV4.getAddress(), [], { version: 5, libraries: { AdministrationUtilsV5: await administrationUtilsV5.getAddress(), EndorsementUtilsV5: await endorsementUtilsV5.getAddress(), VoteEligibilityUtilsV5: await voteEligibilityUtilsV5.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV5 = await x2EarnAppsV5.apps(); (0, chai_1.expect)(appsV4).to.eql(appsV5); // Upgrade X2EarnAppsV5 to X2EarnAppsV6 const x2EarnAppsV6 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV5", "X2EarnAppsV6", await x2EarnAppsV5.getAddress(), [], { version: 6, libraries: { AdministrationUtilsV6: await administrationUtilsV6.getAddress(), EndorsementUtilsV6: await endorsementUtilsV6.getAddress(), VoteEligibilityUtilsV6: await voteEligibilityUtilsV6.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV6 = await x2EarnAppsV6.apps(); (0, chai_1.expect)(appsV5).to.eql(appsV6); // Upgrade X2EarnAppsV6 to X2EarnAppsV7 const x2EarnAppsV7 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV6", "X2EarnAppsV7", await x2EarnAppsV6.getAddress(), [await stargateNftMock.getAddress()], { version: 7, libraries: { AdministrationUtilsV7: await administrationUtilsV7.getAddress(), EndorsementUtilsV7: await endorsementUtilsV7.getAddress(), VoteEligibilityUtilsV7: await voteEligibilityUtilsV7.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV7 = await x2EarnAppsV7.apps(); (0, chai_1.expect)(appsV6).to.eql(appsV7); // Upgrade X2EarnAppsV7 to X2EarnApps (V8 - latest) const x2EarnAppsV8 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV7", "X2EarnApps", await x2EarnAppsV7.getAddress(), [], { version: 8, libraries: { AdministrationUtils: await administrationUtils.getAddress(), EndorsementUtils: await endorsementUtils.getAddress(), VoteEligibilityUtils: await voteEligibilityUtils.getAddress(), AppStorageUtils: await appStorageUtils.getAddress(), }, })); // start new round await (0, helpers_2.startNewAllocationRound)(); const appsV8 = await x2EarnAppsV8.apps(); (0, chai_1.expect)(appsV7).to.eql(appsV8); }); (0, mocha_1.it)("X2Earn Apps added pre contract upgrade should need endorsement after upgrade and should be in grace period", async () => { const config = (0, local_1.createLocalConfig)(); config.EMISSIONS_CYCLE_DURATION = 24; const { xAllocationVoting, x2EarnRewardsPool, xAllocationPool, timeLock, x2EarnCreator, owner, nodeManagement, otherAccounts, veBetterPassport, administrationUtilsV2, endorsementUtilsV2, voteEligibilityUtilsV2, } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy X2EarnApps const x2EarnAppsV1 = (await (0, helpers_1.deployProxy)("X2EarnAppsV1", [ "ipfs://", [await timeLock.getAddress(), owner.address], owner.address, owner.address, ])); await x2EarnRewardsPool.setX2EarnApps(await x2EarnAppsV1.getAddress()); await xAllocationPool.setX2EarnAppsAddress(await x2EarnAppsV1.getAddress()); await xAllocationVoting.setX2EarnAppsAddress(await x2EarnAppsV1.getAddress()); const app1Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); const app2Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #2")); const app3Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #3")); // Create two MjolnirX node holder with an endorsement score of 100 await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[1]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[2]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 // Add apps -> should be eligble for next round await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[2].address, otherAccounts[2].address, "My app", "metadataURI"); await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[3].address, otherAccounts[3].address, "My app #2", "metadataURI"); // start round using V1 contract const round1 = await (0, helpers_2.startNewAllocationRound)(); // Add app -> should be eligble for next round await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[4].address, otherAccounts[4].address, "My app #3", "metadataURI"); // check eligibilty (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app3Id)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round1)).to.eql(false); // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Upgrade X2EarnAppsV1 to X2EarnApps const x2EarnAppsV2 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV1", "X2EarnAppsV2", await x2EarnAppsV1.getAddress(), [ config.XAPP_GRACE_PERIOD, await nodeManagement.getAddress(), await veBetterPassport.getAddress(), await x2EarnCreator.getAddress(), ], { version: 2, libraries: { AdministrationUtilsV2: await administrationUtilsV2.getAddress(), EndorsementUtilsV2: await endorsementUtilsV2.getAddress(), VoteEligibilityUtilsV2: await voteEligibilityUtilsV2.getAddress(), }, })); await veBetterPassport .connect(owner) .grantRole(await veBetterPassport.ACTION_SCORE_MANAGER_ROLE(), await x2EarnAppsV2.getAddress()); // start new round const round2 = await (0, helpers_2.startNewAllocationRound)(); // check eligibilty (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app3Id)).to.eql(true); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round2)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round2)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round2)).to.eql(true); // Need to check the status of the apps so that they SC will reconise apps are unendrosed await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // All apps should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); // 2 out of the three apps get endorsed await x2EarnAppsV2.connect(otherAccounts[1]).endorseApp(app1Id, 1); // Node holder endorsement score is 100 await x2EarnAppsV2.connect(otherAccounts[2]).endorseApp(app2Id, 2); // Node holder endorsement score is 100 // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Need to check the status of the apps so that they SC will reconise apps are unendrosed ans track grace period await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // start new round const round3 = await (0, helpers_2.startNewAllocationRound)(); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round3)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round3)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round3)).to.eql(true); // Only 1 app should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Need to check the status of the apps so that they SC will reconise apps are unendrosed and track grace period await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // start new round -> app3Id has had two rounds unendorsed so it is no longer in grace period and not eligeble for voting const round4 = await (0, helpers_2.startNewAllocationRound)(); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round4)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round4)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round4)).to.eql(false); // Only 1 app should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); }); (0, mocha_1.it)("Vechain nodes that starting endorsing XApps priod to upgrade or not subject to cooldown period but will be after they perform an action.", async () => { const config = (0, local_1.createLocalConfig)(); config.EMISSIONS_CYCLE_DURATION = 24; config.X2EARN_NODE_COOLDOWN_PERIOD = 1; const { xAllocationVoting, x2EarnRewardsPool, xAllocationPool, timeLock, x2EarnCreator, owner, nodeManagement, otherAccounts, veBetterPassport, administrationUtilsV2, endorsementUtilsV2, voteEligibilityUtilsV2, administrationUtilsV3, endorsementUtilsV3, voteEligibilityUtilsV3, administrationUtilsV4, endorsementUtilsV4, voteEligibilityUtilsV4, administrationUtilsV5, endorsementUtilsV5, voteEligibilityUtilsV5, administrationUtils, endorsementUtils, voteEligibilityUtils, appStorageUtils, } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy X2EarnApps const x2EarnAppsV1 = (await (0, helpers_1.deployProxy)("X2EarnAppsV1", [ "ipfs://", [await timeLock.getAddress(), owner.address], owner.address, owner.address, ])); await x2EarnRewardsPool.setX2EarnApps(await x2EarnAppsV1.getAddress()); await xAllocationPool.setX2EarnAppsAddress(await x2EarnAppsV1.getAddress()); await xAllocationVoting.setX2EarnAppsAddress(await x2EarnAppsV1.getAddress()); const app1Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); const app2Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #2")); const app3Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #3")); // Create two MjolnirX node holder with an endorsement score of 100 const nodeId1 = await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[1]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 const nodeId2 = await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[2]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 // Add apps -> should be eligble for next round await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[2].address, otherAccounts[2].address, "My app", "metadataURI"); await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[3].address, otherAccounts[3].address, "My app #2", "metadataURI"); // start round using V1 contract const round1 = await (0, helpers_2.startNewAllocationRound)(); // Add app -> should be eligble for next round await x2EarnAppsV1 .connect(owner) .addApp(otherAccounts[4].address, otherAccounts[4].address, "My app #3", "metadataURI"); // check eligibilty (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV1.isEligibleNow(app3Id)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round1)).to.eql(false); // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Upgrade X2EarnAppsV1 to X2EarnApps const x2EarnAppsV2 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV1", "X2EarnAppsV2", await x2EarnAppsV1.getAddress(), [ config.XAPP_GRACE_PERIOD, await nodeManagement.getAddress(), await veBetterPassport.getAddress(), await x2EarnCreator.getAddress(), ], { version: 2, libraries: { AdministrationUtilsV2: await administrationUtilsV2.getAddress(), EndorsementUtilsV2: await endorsementUtilsV2.getAddress(), VoteEligibilityUtilsV2: await voteEligibilityUtilsV2.getAddress(), }, })); await veBetterPassport .connect(owner) .grantRole(await veBetterPassport.ACTION_SCORE_MANAGER_ROLE(), await x2EarnAppsV2.getAddress()); // start new round const round2 = await (0, helpers_2.startNewAllocationRound)(); // check eligibilty (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app3Id)).to.eql(true); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round2)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round2)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round2)).to.eql(true); // Need to check the status of the apps so that they SC will reconise apps are unendrosed await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // All apps should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); // 2 out of the three apps get endorsed await x2EarnAppsV2.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 await x2EarnAppsV2.connect(otherAccounts[2]).endorseApp(app2Id, nodeId2); // Node holder endorsement score is 100 // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Need to check the status of the apps so that they SC will reconise apps are unendrosed ans track grace period await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // start new round const round3 = await (0, helpers_2.startNewAllocationRound)(); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round3)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round3)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round3)).to.eql(true); // Only 1 app should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); // Need to check the status of the apps so that they SC will reconise apps are unendrosed and track grace period await x2EarnAppsV2.checkEndorsement(app1Id); await x2EarnAppsV2.checkEndorsement(app2Id); await x2EarnAppsV2.checkEndorsement(app3Id); // start new round -> app3Id has had two rounds unendorsed so it is no longer in grace period and not eligeble for voting const round4 = await (0, helpers_2.startNewAllocationRound)(); // All apps should be eligible now (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round4)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round4)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round4)).to.eql(false); // Only 1 app should be seeking endorsement (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app2Id)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app3Id)).to.eql(true); // Prior to upgrade node holder can endorse apps without being subject to cooldown period await x2EarnAppsV2.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(true); await x2EarnAppsV2.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); await x2EarnAppsV2.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(true); await x2EarnAppsV2.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV2.isAppUnendorsed(app1Id)).to.eql(false); // Create new node holders with an endorsement score of 100 const nodeId3 = await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[5]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 const nodeId4 = await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[6]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 // app3Id just gets endorsed await x2EarnAppsV2.connect(otherAccounts[6]).endorseApp(app3Id, nodeId4); // Upgrade X2EarnAppsV3 to X2EarnAppsV2 const x2EarnAppsV3 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV2", "X2EarnAppsV3", await x2EarnAppsV2.getAddress(), [config.X2EARN_NODE_COOLDOWN_PERIOD, await xAllocationVoting.getAddress()], { version: 3, libraries: { AdministrationUtilsV3: await administrationUtilsV3.getAddress(), EndorsementUtilsV3: await endorsementUtilsV3.getAddress(), VoteEligibilityUtilsV3: await voteEligibilityUtilsV3.getAddress(), }, })); // New node holders should not be subject to cooldown period even if they endorse an app prior to upgrade (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId3)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId4)).to.eql(false); // Node holders that endorsed an app prior to upgrade should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId1)).to.eql(false); // If a node holder that endorsed an app prior to upgrade performs an action they should be subject to cooldown period await x2EarnAppsV3.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 await x2EarnAppsV3.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId1)).to.eql(true); // Should revert if user in cooldown period tries to endorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV3.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1)); await x2EarnAppsV3 .connect(creator1) .submitApp(otherAccounts[4].address, otherAccounts[4].address, "My app 4", "metadataURI"); const app4Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app 4")); // New node holders should be subject to cooldown period await (0, helpers_2.catchRevert)(x2EarnAppsV3.connect(otherAccounts[6]).endorseApp(app4Id, nodeId4)); // Fast forward time to next round // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); await (0, helpers_2.startNewAllocationRound)(); // New node holders should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId1)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId2)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV3.checkCooldown(nodeId3)).to.eql(false); // Upgrade X2EarnAppsV3 to X2EarnApps const x2EarnAppsV4 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV3", "X2EarnAppsV4", await x2EarnAppsV3.getAddress(), [await x2EarnRewardsPool.getAddress()], { version: 4, libraries: { AdministrationUtilsV4: await administrationUtilsV4.getAddress(), EndorsementUtilsV4: await endorsementUtilsV4.getAddress(), VoteEligibilityUtilsV4: await voteEligibilityUtilsV4.getAddress(), }, })); // New node holders should not be subject to cooldown period even if they endorse an app prior to upgrade (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId1)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId2)).to.eql(false); // Node holders that endorsed an app prior to upgrade should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId1)).to.eql(false); // If a node holder that endorsed an app prior to upgrade performs an action they should be subject to cooldown period await x2EarnAppsV4.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 await x2EarnAppsV4.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId1)).to.eql(true); // Should revert if user in cooldown period tries to endorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV4.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1)); await x2EarnAppsV4 .connect(creator2) .submitApp(otherAccounts[4].address, otherAccounts[4].address, "My app 5", "metadataURI"); const app5Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app 5")); // New node holders should be subject to cooldown period await (0, helpers_2.catchRevert)(x2EarnAppsV4.connect(otherAccounts[6]).endorseApp(app5Id, nodeId4)); // Fast forward time to next round // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); await (0, helpers_2.startNewAllocationRound)(); // New node holders should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId1)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId2)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV4.checkCooldown(nodeId3)).to.eql(false); // Upgrade X2EarnAppsV4 to X2EarnAppsV5 const x2EarnAppsV5 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV4", "X2EarnAppsV5", await x2EarnAppsV4.getAddress(), [], { version: 5, libraries: { AdministrationUtilsV5: await administrationUtilsV5.getAddress(), EndorsementUtilsV5: await endorsementUtilsV5.getAddress(), VoteEligibilityUtilsV5: await voteEligibilityUtilsV5.getAddress(), }, })); // New node holders should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId1)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId2)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId3)).to.eql(false); // If a node holder that endorsed an app prior to upgrade performs an action they should be subject to cooldown period await x2EarnAppsV5.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 await x2EarnAppsV5.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1); // Node holder endorsement score is 100 (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId1)).to.eql(true); // Should revert if user in cooldown period tries to endorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV5.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1)); // Should revert if user in cooldown period tries to unendorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV5.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1)); // Should revert if user in cooldown period tries to endorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV5.connect(otherAccounts[1]).endorseApp(app1Id, nodeId1)); // Should revert if user in cooldown period tries to unendorse an app await (0, helpers_2.catchRevert)(x2EarnAppsV5.connect(otherAccounts[1]).unendorseApp(app1Id, nodeId1)); await x2EarnAppsV5 .connect(creator3) .submitApp(otherAccounts[4].address, otherAccounts[4].address, "My app 6", "metadataURI"); const app6Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app 6")); // New node holders should be subject to cooldown period await (0, helpers_2.catchRevert)(x2EarnAppsV5.connect(otherAccounts[6]).endorseApp(app6Id, nodeId4)); // Fast forward time to next round // wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); await (0, helpers_2.startNewAllocationRound)(); // New node holders should not be subject to cooldown period (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId1)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId2)).to.eql(false); (0, chai_1.expect)(await x2EarnAppsV5.checkCooldown(nodeId3)).to.eql(false); }); (0, mocha_1.it)("Should not have state conflict after upgrading to V6", async () => { const config = (0, local_1.createLocalConfig)(); config.EMISSIONS_CYCLE_DURATION = 24; config.X2EARN_NODE_COOLDOWN_PERIOD = 1; const { xAllocationVoting, x2EarnRewardsPool, xAllocationPool, timeLock, owner, otherAccounts, veBetterPassport, endorsementUtils, administrationUtils, voteEligibilityUtils, appStorageUtils, nodeManagement, x2EarnCreator, administrationUtilsV2, endorsementUtilsV2, voteEligibilityUtilsV2, administrationUtilsV3, endorsementUtilsV3, voteEligibilityUtilsV3, administrationUtilsV4, endorsementUtilsV4, voteEligibilityUtilsV4, administrationUtilsV5, endorsementUtilsV5, voteEligibilityUtilsV5, administrationUtilsV6, endorsementUtilsV6, voteEligibilityUtilsV6, } = await (0, helpers_2.getOrDeployContractInstances)({ forceDeploy: true }); const x2EarnAppsV2 = (await (0, helpers_1.deployAndUpgrade)(["X2EarnAppsV1", "X2EarnAppsV2"], [ ["ipfs://", [await timeLock.getAddress(), owner.address], owner.address, owner.address], [ config.XAPP_GRACE_PERIOD, await nodeManagement.getAddress(), await veBetterPassport.getAddress(), await x2EarnCreator.getAddress(), ], ], { versions: [undefined, 2], libraries: [ undefined, { AdministrationUtilsV2: await administrationUtilsV2.getAddress(), EndorsementUtilsV2: await endorsementUtilsV2.getAddress(), VoteEligibilityUtilsV2: await voteEligibilityUtilsV2.getAddress(), }, ], })); // Grant Roles // Grant minter and burner role to X2Earn contract await x2EarnCreator.connect(owner).grantRole(await x2EarnCreator.MINTER_ROLE(), await x2EarnAppsV2.getAddress()); await x2EarnCreator.connect(owner).grantRole(await x2EarnCreator.BURNER_ROLE(), await x2EarnAppsV2.getAddress()); // Grant the ACTION_SCORE_MANAGER_ROLE to X2Earn contract await veBetterPassport .grantRole(await veBetterPassport.ACTION_SCORE_MANAGER_ROLE(), await x2EarnAppsV2.getAddress()) .then(async (tx) => await tx.wait()); await x2EarnRewardsPool.setX2EarnApps(await x2EarnAppsV2.getAddress()); await xAllocationPool.setX2EarnAppsAddress(await x2EarnAppsV2.getAddress()); await xAllocationVoting.setX2EarnAppsAddress(await x2EarnAppsV2.getAddress()); const app1Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); const app2Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #2")); const app3Id = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #3")); // Create two MjolnirX node holders with an endorsement score of 100 await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[1]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[2]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 // Add apps -> should be eligible for the next round await x2EarnAppsV2 .connect(owner) .submitApp(otherAccounts[2].address, otherAccounts[2].address, "My app", "metadataURI"); await x2EarnAppsV2 .connect(owner) .submitApp(otherAccounts[3].address, otherAccounts[3].address, "My app #2", "metadataURI"); await x2EarnAppsV2.connect(otherAccounts[1]).endorseApp(app1Id, 1); await x2EarnAppsV2.connect(otherAccounts[2]).endorseApp(app2Id, 2); // Start round using V1 contract const round1 = await (0, helpers_2.startNewAllocationRound)(); // Add app -> should be eligible for the next round await x2EarnAppsV2 .connect(owner) .submitApp(otherAccounts[4].address, otherAccounts[4].address, "My app #3", "metadataURI"); await (0, xnodes_1.createLegacyNodeHolder)(7, otherAccounts[4]); // Node strength level 7 corresponds (MjolnirX) to an endorsement score of 100 await x2EarnAppsV2.connect(otherAccounts[4]).endorseApp(app3Id, 3); // Check eligibility (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app1Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app2Id)).to.eql(true); (0, chai_1.expect)(await x2EarnAppsV2.isEligibleNow(app3Id)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app1Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app2Id, round1)).to.eql(true); (0, chai_1.expect)(await xAllocationVoting.isEligibleForVote(app3Id, round1)).to.eql(false); // Wait for round to end await (0, helpers_2.waitForCurrentRoundToEnd)(); const initialSlotVoteEligibility = BigInt("0xb5b8d618af1ffb8d5bcc4bd23f445ba34ed08d7a16d1e1b5411cfbe7913e5900"); const initialSlotSettings = BigInt("0x83b9a7e51f394efa93107c3888716138908bbbe611dfc86afa3639a826441100"); const initialSlotAppsStorage = BigInt("0xb6909058bd527140b8d55a44344c5e42f1f148f1b3b16df7641882df8dd72900"); const initialSlotAdministration = BigInt("0x5830f0e95c01712d916c34d9e2fa42e9f749b325b67bce7382d70bb99c623500"); const initialEndorsementSlot = BigInt("0xc1a7bcdc0c77e8c77ade4541d1777901ab96ca598d164d89afa5c8dfbfc44300"); const storageSlots = await (0, helpers_2.getStorageSlots)(x2EarnAppsV2.getAddress(), initialSlotVoteEligibility, initialSlotSettings, initialSlotAppsStorage, initialSlotAdministration, initialEndorsementSlot); config.X2EARN_NODE_COOLDOWN_PERIOD = 24; // Upgrade X2EarnAppsV2 to X2EarnAppsV3 const x2EarnAppsV3 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV2", "X2EarnAppsV3", await x2EarnAppsV2.getAddress(), [config.X2EARN_NODE_COOLDOWN_PERIOD, await xAllocationVoting.getAddress()], { version: 3, libraries: { AdministrationUtilsV3: await administrationUtilsV3.getAddress(), EndorsementUtilsV3: await endorsementUtilsV3.getAddress(), VoteEligibilityUtilsV3: await voteEligibilityUtilsV3.getAddress(), }, })); const storageSlotsAfterV3 = await (0, helpers_2.getStorageSlots)(x2EarnAppsV3.getAddress(), initialSlotVoteEligibility, initialSlotSettings, initialSlotAppsStorage, initialSlotAdministration, initialEndorsementSlot); (0, chai_1.expect)(await x2EarnAppsV3.version()).to.equal("3"); (0, chai_1.expect)(storageSlotsAfterV3[storageSlotsAfterV3.length - 2]).to.equal(BigInt(config.X2EARN_NODE_COOLDOWN_PERIOD)); for (let i = 0; i < storageSlots.length; i++) { (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfterV3[i]); } const storageSlotsAdministrationAfterV3 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAdministration); const storageSlotsVoteEligibilityAfterV3 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotVoteEligibility); const storageSlotsSettingsAfterV3 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotSettings); const storageSlotsAppsStorageAfterV3 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAppsStorage); const storageSlotsEndorsementSlotAfterV3 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialEndorsementSlot); // x2EarnAppsV4 const x2EarnAppsV4 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV3", "X2EarnAppsV4", await x2EarnAppsV3.getAddress(), [await x2EarnRewardsPool.getAddress()], { version: 4, libraries: { AdministrationUtilsV4: await administrationUtilsV4.getAddress(), EndorsementUtilsV4: await endorsementUtilsV4.getAddress(), VoteEligibilityUtilsV4: await voteEligibilityUtilsV4.getAddress(), }, })); const storageSlotsAdministrationAfterV4 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAdministration); const storageSlotsVoteEligibilityAfterV4 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotVoteEligibility); const storageSlotsSettingsAfterV4 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotSettings); const storageSlotsAppsStorageAfterV4 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAppsStorage); const storageSlotsEndorsementSlotAfterV4 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialEndorsementSlot); (0, chai_1.expect)(await x2EarnAppsV4.version()).to.equal("4"); // Check that the storage slots are the same for the administration module for (let i = 0; i < storageSlotsAdministrationAfterV3.length; i++) { (0, chai_1.expect)(storageSlotsAdministrationAfterV3[i]).to.equal(storageSlotsAdministrationAfterV4[i]); } // Check that the storage slots are the same for the vote eligibility module for (let i = 0; i < storageSlotsVoteEligibilityAfterV3.length; i++) { (0, chai_1.expect)(storageSlotsVoteEligibilityAfterV3[i]).to.equal(storageSlotsVoteEligibilityAfterV4[i]); } // Check that the storage slots are the same for the settings module for (let i = 0; i < storageSlotsSettingsAfterV3.length; i++) { (0, chai_1.expect)(storageSlotsSettingsAfterV3[i]).to.equal(storageSlotsSettingsAfterV4[i]); } // Check that the storage slots are the same for the apps storage module for (let i = 0; i < storageSlotsAppsStorageAfterV3.length; i++) { (0, chai_1.expect)(storageSlotsAppsStorageAfterV3[i]).to.equal(storageSlotsAppsStorageAfterV4[i]); } // Check that the storage slots are the same for the endorsement slot for (let i = 0; i < storageSlotsEndorsementSlotAfterV3.length; i++) { (0, chai_1.expect)(storageSlotsEndorsementSlotAfterV3[i]).to.equal(storageSlotsEndorsementSlotAfterV4[i]); } // The first slot is the x2earnCreator contract address const addressFromSlot = hardhat_1.ethers.getAddress("0x" + storageSlotsAdministrationAfterV4[0].slice(26)); const expectedAddress = hardhat_1.ethers.getAddress(await x2EarnCreator.getAddress()); (0, chai_1.expect)(addressFromSlot).to.equal(expectedAddress); // The second slot is the x2earnRewardsPool contract address const addressFromSlot2 = hardhat_1.ethers.getAddress("0x" + storageSlotsAdministrationAfterV4[1].slice(26)); const expectedAddress2 = hardhat_1.ethers.getAddress(await x2EarnRewardsPool.getAddress()); (0, chai_1.expect)(addressFromSlot2).to.equal(expectedAddress2); // Upgrade to V5 const x2EarnAppsV5 = (await (0, helpers_1.upgradeProxy)("X2EarnAppsV4", "X2EarnAppsV5", await x2EarnAppsV4.getAddress(), [], { version: 5, libraries: { AdministrationUtilsV5: await administrationUtilsV5.getAddress(), EndorsementUtilsV5: await endorsementUtilsV5.getAddress(), VoteEligibilityUtilsV5: await voteEligibilityUtilsV5.getAddress(), }, })); const storageSlotsAdministrationAfterV5 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAdministration); const storageSlotsVoteEligibilityAfterV5 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotVoteEligibility); const storageSlotsSettingsAfterV5 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotSettings); const storageSlotsAppsStorageAfterV5 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialSlotAppsStorage); const storageSlotsEndorsementSlotAfterV5 = await (0, helpers_2.getStorageSlots)(await x2EarnAppsV2.getAddress(), initialEndorsementSlot); // check that the version is good (0, chai_1.expect)(await x2EarnAppsV5.version()).to.eql("5"); // Check that the storage slots are the same for the administration module