UNPKG

@vechain/vebetterdao-contracts

Version:

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

584 lines (583 loc) 41.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const helpers_1 = require("../helpers"); const local_1 = require("@repo/config/contracts/envs/local"); const common_1 = require("../helpers/common"); const helpers_2 = require("../../scripts/helpers"); const chai_1 = require("chai"); const hardhat_1 = require("hardhat"); let owner; let b3tr; let treasury; let nodeHolder; let secondaryWallet; let config; let xAllocationVoting; let governor; let otherAccount; let stargateNftMock; let minterAccount; let otherAccounts; let nodeManagement; let vechainNodes; let stargateMock; describe("Galaxy Member - V6 Upgrade - @shard3b", function () { beforeEach(async function () { config = (0, local_1.createLocalConfig)(); const contracts = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, deployMocks: true, }); owner = contracts.owner; b3tr = contracts.b3tr; treasury = contracts.treasury; nodeHolder = contracts.otherAccounts[0]; secondaryWallet = contracts.otherAccounts[10]; xAllocationVoting = contracts.xAllocationVoting; governor = contracts.governor; otherAccount = contracts.otherAccount; stargateNftMock = contracts.stargateNftMock; minterAccount = contracts.minterAccount; otherAccounts = contracts.otherAccounts; nodeManagement = contracts.nodeManagement; vechainNodes = contracts.vechainNodesMock; stargateMock = contracts.stargateMock; }); it("Token minted in V1 should persist until V6", async function () { // Deploy with correct b3tr required to upgrade const galaxyMemberV1 = (await (0, helpers_2.deployProxy)("GalaxyMemberV1", [ { name: helpers_1.NFT_NAME, symbol: helpers_1.NFT_SYMBOL, admin: owner.address, upgrader: owner.address, pauser: owner.address, minter: owner.address, contractsAddressManager: owner.address, maxLevel: 2, baseTokenURI: config.GM_NFT_BASE_URI, b3trToUpgradeToLevel: [10000000000000000000000n], b3tr: await b3tr.getAddress(), treasury: await treasury.getAddress(), }, ])); await galaxyMemberV1.waitForDeployment(); await galaxyMemberV1.connect(owner).setXAllocationsGovernorAddress(await xAllocationVoting.getAddress()); await galaxyMemberV1.connect(owner).setB3trGovernorAddress(await governor.getAddress()); //Should be in version 1 (0, chai_1.expect)(await galaxyMemberV1.version()).to.equal("1"); // Bootstrap emissions await (0, common_1.bootstrapEmissions)(); // participation in governance is a requirement for minting await (0, common_1.participateInAllocationVoting)(otherAccount); // Mint first token await galaxyMemberV1.connect(otherAccount).freeMint(); //Should be the first token id (0, chai_1.expect)(await galaxyMemberV1.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); //Upgrade to V2 const galaxyMemberV2 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV1", "GalaxyMemberV2", await galaxyMemberV1.getAddress(), [owner.address, await nodeManagement.getAddress(), owner.address, config.GM_NFT_NODE_TO_FREE_LEVEL], { version: 2 })); //Should be in version 2 (0, chai_1.expect)(await galaxyMemberV2.version()).to.equal("2"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV2.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); //Upgrade to V3 const galaxyMemberV3 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV2", "GalaxyMemberV3", await galaxyMemberV2.getAddress(), [], { version: 3 })); //Should be in version 3 (0, chai_1.expect)(await galaxyMemberV3.version()).to.equal("3"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV3.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); //Upgrade to V4 const galaxyMemberV4 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV3", "GalaxyMemberV4", await galaxyMemberV3.getAddress(), [], { version: 4 })); //Should be in version 4 (0, chai_1.expect)(await galaxyMemberV4.version()).to.equal("4"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV4.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); //Upgrade to V5 const galaxyMemberV5 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV4", "GalaxyMemberV5", await galaxyMemberV4.getAddress(), [], { version: 5 })); //Should be in version 5 (0, chai_1.expect)(await galaxyMemberV5.version()).to.equal("5"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV5.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); //Upgrade to V6 const galaxyMemberV6 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV5", "GalaxyMember", await galaxyMemberV5.getAddress(), [await stargateNftMock.getAddress()], { version: 6 })); //Should be in version 6 (0, chai_1.expect)(await galaxyMemberV6.version()).to.equal("6"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV6.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); }); it("Token minted in V5 should persist through V6 upgrade", async function () { // Deploy with correct b3tr required to upgrade const galaxyMemberV5 = (await (0, helpers_2.deployProxy)("GalaxyMemberV5", [ { name: helpers_1.NFT_NAME, symbol: helpers_1.NFT_SYMBOL, admin: owner.address, upgrader: owner.address, pauser: owner.address, minter: owner.address, contractsAddressManager: owner.address, maxLevel: 2, baseTokenURI: config.GM_NFT_BASE_URI, b3trToUpgradeToLevel: [10000000000000000000000n], b3tr: await b3tr.getAddress(), treasury: await treasury.getAddress(), }, ])); await galaxyMemberV5.waitForDeployment(); await galaxyMemberV5.connect(owner).setXAllocationsGovernorAddress(await xAllocationVoting.getAddress()); await galaxyMemberV5.connect(owner).setB3trGovernorAddress(await governor.getAddress()); //Should be in version 5 (0, chai_1.expect)(await galaxyMemberV5.version()).to.equal("5"); //Bootstrap emissions await (0, common_1.bootstrapEmissions)(); //Participate in governance await (0, common_1.participateInAllocationVoting)(otherAccount, true, otherAccount); await (0, common_1.participateInAllocationVoting)(owner, false, owner); //Mint token await galaxyMemberV5.connect(otherAccount).freeMint(); // token id 0 await galaxyMemberV5.connect(owner).freeMint(); // token id 1 //Should be in version 6 (0, chai_1.expect)(await galaxyMemberV5.version()).to.equal("5"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV5.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); // token id 0 (0, chai_1.expect)(await galaxyMemberV5.tokenOfOwnerByIndex(await owner.getAddress(), 0)).to.equal(1); // token id 1 //Upgrade to V6 const galaxyMemberV6 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV5", "GalaxyMember", await galaxyMemberV5.getAddress(), [await stargateNftMock.getAddress()], { version: 6 })); //Should be in version 6 (0, chai_1.expect)(await galaxyMemberV6.version()).to.equal("6"); //Should have the same token id (0, chai_1.expect)(await galaxyMemberV6.tokenOfOwnerByIndex(await otherAccount.getAddress(), 0)).to.equal(0); // token id 0 (0, chai_1.expect)(await galaxyMemberV6.tokenOfOwnerByIndex(await owner.getAddress(), 0)).to.equal(1); // token id 1 }); it("Should NOT have state conflict after upgrading to V6 if node is migrated to Stargate before upgrading", async () => { // Bootstrap emissions await (0, common_1.bootstrapEmissions)(); // Should be able to free mint after participating in allocation voting await (0, common_1.participateInAllocationVoting)(owner, false, otherAccounts[10]); const galaxyMember = (await (0, helpers_2.deployProxy)("GalaxyMemberV1", [ { name: helpers_1.NFT_NAME, symbol: helpers_1.NFT_SYMBOL, admin: owner.address, upgrader: owner.address, pauser: owner.address, minter: owner.address, contractsAddressManager: owner.address, maxLevel: 5, baseTokenURI: config.GM_NFT_BASE_URI, b3trToUpgradeToLevel: config.GM_NFT_B3TR_REQUIRED_TO_UPGRADE_TO_LEVEL, b3tr: await b3tr.getAddress(), treasury: await treasury.getAddress(), }, ])); await galaxyMember.waitForDeployment(); (0, chai_1.expect)(await galaxyMember.MAX_LEVEL()).to.equal(5); // Contract setup await galaxyMember.connect(owner).setB3trGovernorAddress(await governor.getAddress()); await galaxyMember.connect(owner).setXAllocationsGovernorAddress(await xAllocationVoting.getAddress()); // Participation in governance is a requirement for minting const participated = await galaxyMember.connect(owner).participatedInGovernance(owner); (0, chai_1.expect)(participated).to.equal(true); // Mint 4 tokens to owner await galaxyMember.connect(owner).freeMint(); // gmId 0 await galaxyMember.connect(owner).burn(0); // gmId 0 await galaxyMember.connect(owner).freeMint(); // gmId 1 await galaxyMember.connect(owner).freeMint(); // gmId 2 await galaxyMember.connect(owner).freeMint(); // gmId 3 await galaxyMember.connect(owner).freeMint(); // gmId 4 (0, chai_1.expect)(await galaxyMember.balanceOf(await owner.getAddress())).to.equal(4); // Transfer GM NFTs to other accounts: otherAccount, otherAccounts[0], otherAccounts[1] await galaxyMember.connect(owner)["safeTransferFrom(address,address,uint256)"](owner, otherAccount, 1); await galaxyMember.connect(owner).transferFrom(owner.address, otherAccounts[0].address, 2); await galaxyMember.connect(owner).transferFrom(owner.address, otherAccounts[1].address, 3); // All 4 accounts hold 1 GM NFT each (0, chai_1.expect)(await galaxyMember.balanceOf(await owner.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMember.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMember.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMember.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMember.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMember.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMember.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMember.ownerOf(4)).to.equal(await owner.getAddress()); // All GMs are of level 1 (0, chai_1.expect)(await galaxyMember.levelOf(1)).to.equal(1); // Earth (0, chai_1.expect)(await galaxyMember.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMember.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMember.levelOf(4)).to.equal(1); let storageSlots = []; const initialSlot = BigInt("0x7a79e46844ed04411e4579c7bc49d053e59b0854fa4e9a8df3d5a0597ce45200"); // Slot 0 of GalaxyMember for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlots.push(await hardhat_1.ethers.provider.getStorage(await galaxyMember.getAddress(), i)); } storageSlots = storageSlots.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // removing empty slots const galaxyMemberV2 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV1", "GalaxyMemberV2", await galaxyMember.getAddress(), [owner.address, await nodeManagement.getAddress(), owner.address, config.GM_NFT_NODE_TO_FREE_LEVEL], { version: 2 })); let storageSlotsAfter = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlotsAfter.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV2.getAddress(), i)); } storageSlotsAfter = storageSlotsAfter.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // removing empty slots // Check if storage slots are the same after upgrade for (let i = 0; i < storageSlots.length; i++) { // console.log("*** storageSlots v1", storageSlots[i], "vs v2", storageSlotsAfter[i]) (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfter[i]); } // Contract setup await galaxyMemberV2.setVechainNodes(await vechainNodes.getAddress()); (0, chai_1.expect)(await galaxyMemberV2.MAX_LEVEL()).to.equal(5); await galaxyMemberV2.setMaxLevel(10); (0, chai_1.expect)(await galaxyMemberV2.MAX_LEVEL()).to.equal(10); // Check if all GM NFTs are still owned by the original owners (0, chai_1.expect)(await galaxyMemberV2.balanceOf(await owner.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMemberV2.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMemberV2.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV2.ownerOf(4)).to.equal(await owner.getAddress()); // All GMs are still of level 1 (0, chai_1.expect)(await galaxyMemberV2.levelOf(1)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV2.levelOf(4)).to.equal(1); // Mint a new GM NFT to owner await galaxyMemberV2.connect(owner).freeMint(); (0, chai_1.expect)(await galaxyMemberV2.balanceOf(await owner.getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV2.ownerOf(5)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV2.levelOf(5)).to.equal(1); // Earth // Let's upgrade gmId 1, owned by otherAccount, to level 2 await (0, common_1.upgradeNFTtoLevel)(1, 2, galaxyMemberV2, b3tr, otherAccount, minterAccount); (0, chai_1.expect)(await galaxyMemberV2.levelOf(1)).to.equal(2); // Moon // Mint Mjolnir X Node to otherAccount await (0, common_1.mintLegacyNode)(7, otherAccount); const nodeId = 1; //Should be the first minted (0, chai_1.expect)(await vechainNodes.idToOwner(nodeId)).to.equal(await otherAccount.getAddress()); // Expect a free upgrade to level 7 when attaching a Mjolnir X Node to a GM NFT of a lower level (0, chai_1.expect)(await galaxyMemberV2.getLevelAfterAttachingNode(1, nodeId)).to.equal(7); // Attach nodeId 2 to gmId 1 await galaxyMemberV2.connect(otherAccount).attachNode(nodeId, 1); (0, chai_1.expect)(await galaxyMemberV2.levelOf(1)).to.equal(7); // Saturn (0, chai_1.expect)(await galaxyMemberV2.tokenURI(1)).to.equal(config.GM_NFT_BASE_URI + "7.json"); storageSlots = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlots.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV2.getAddress(), i)); } storageSlots = storageSlots.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); const galaxyMemberV3 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV2", "GalaxyMemberV3", await galaxyMember.getAddress(), [], { version: 3 })); storageSlotsAfter = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlotsAfter.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV3.getAddress(), i)); } storageSlotsAfter = storageSlotsAfter.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // Check if storage slots are the same after upgrade for (let i = 0; i < storageSlots.length; i++) { // console.log("*** storageSlots v2", storageSlots[i], "vs v3", storageSlotsAfter[i]) (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfter[i]); } // Check if all GM NFTs are still owned by the original owners (0, chai_1.expect)(await galaxyMemberV3.balanceOf(await owner.getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV3.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(4)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(5)).to.equal(await owner.getAddress()); // Check that existing GM NFTs have the same level (0, chai_1.expect)(await galaxyMemberV3.levelOf(1)).to.equal(7); (0, chai_1.expect)(await galaxyMemberV3.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(4)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(5)).to.equal(1); // Mint a new GM NFT to owner await galaxyMemberV3.connect(owner).freeMint(); (0, chai_1.expect)(await galaxyMemberV3.balanceOf(await owner.getAddress())).to.equal(3); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(6)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV3.levelOf(6)).to.equal(1); // Earth // Get selected token Id at block number - since you can hold +1 GM NFT, select one to boost rewards (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenIdAtBlock(owner.address, await hardhat_1.ethers.provider.getBlockNumber())).to.equal(0n); // admin selects gmId 4 as part of upgrade await galaxyMemberV3.connect(owner).selectFor(owner.getAddress(), 4); (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenId(owner.getAddress())).to.equal(4); // Get selected gmId at block number (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenIdAtBlock(owner.address, await hardhat_1.ethers.provider.getBlockNumber())).to.equal(4n); // Transfer gmId 4 to otherAccounts[6] - upon transfer, if the `from` address had that id selected, // and if they own other GM NFTs, the "first" one is selected await galaxyMemberV3.connect(owner).transferFrom(owner.address, otherAccounts[6].address, 4); (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenId(owner.getAddress())).to.equal(6n); // otherAccounts[6] (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenIdAtBlock(owner.address, await hardhat_1.ethers.provider.getBlockNumber())).to.equal(6n); // Check if the token is transferred (0, chai_1.expect)(await galaxyMemberV3.ownerOf(4)).to.equal(await otherAccounts[6].getAddress()); // Get selected token Id at block number for the transfer recipient (0, chai_1.expect)(await galaxyMemberV3.getSelectedTokenIdAtBlock(otherAccounts[6].address, await hardhat_1.ethers.provider.getBlockNumber())).to.equal(4n); storageSlots = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlots.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV3.getAddress(), i)); } storageSlots = storageSlots.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); const galaxyMemberV4 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV3", "GalaxyMemberV4", await galaxyMember.getAddress(), [], { version: 4 })); storageSlotsAfter = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlotsAfter.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV4.getAddress(), i)); } storageSlotsAfter = storageSlotsAfter.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // Check if storage slots are the same after upgrade for (let i = 0; i < storageSlots.length; i++) { // console.log("*** storageSlots v3", storageSlots[i], "vs v4", storageSlotsAfter[i]) (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfter[i]); } // Check if all GM NFTs are still owned by the original owners (0, chai_1.expect)(await galaxyMemberV4.balanceOf(await owner.getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV4.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV4.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV4.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV4.balanceOf(await otherAccounts[6].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV4.ownerOf(4)).to.equal(await otherAccounts[6].getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(5)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV3.ownerOf(6)).to.equal(await owner.getAddress()); // Check that existing GM NFTs have the same level (0, chai_1.expect)(await galaxyMemberV3.levelOf(1)).to.equal(7); (0, chai_1.expect)(await galaxyMemberV3.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(4)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(5)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV3.levelOf(6)).to.equal(1); // Transfer gmId 6 to otherAccounts[6] await galaxyMemberV4.connect(owner).transferFrom(owner.address, otherAccounts[6].address, 6); // Check if the token is transferred (0, chai_1.expect)(await galaxyMemberV4.ownerOf(6)).to.equal(await otherAccounts[6].getAddress()); // Check token selection (0, chai_1.expect)(await galaxyMemberV4.getSelectedTokenId(owner.getAddress())).to.equal(5n); // defaults to the first token (0, chai_1.expect)(await galaxyMemberV4.getSelectedTokenId(otherAccounts[6].getAddress())).to.equal(4n); // otherAccounts[6] had 4 selected // V5 is about pointing nodeManagement to version 3, and deprecate the usage of tokenAuction contract // Before the upgrade, I can correctly check the level of the vechain node (0, chai_1.expect)(await galaxyMemberV4.getNodeLevelOf(nodeId)).to.equal(7); // The node is still attached to the GM NFT, resulting on the GM NFT having level 7 (0, chai_1.expect)(await galaxyMemberV4.getIdAttachedToNode(nodeId)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV4.levelOf(1)).to.equal(7); storageSlots = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlots.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV4.getAddress(), i)); } storageSlots = storageSlots.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // before the upgrade, we save the mapping _nodeToFreeUpgradeLevel values (to check later) const levels = await stargateNftMock.getLevels(); const freeUpgradeLevels = []; for (const level of levels) { const freeUpgradeLevel = await galaxyMemberV4.getNodeToFreeLevel(level.id); freeUpgradeLevels.push(freeUpgradeLevel); } const galaxyMemberV5 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV4", "GalaxyMemberV5", await galaxyMember.getAddress(), [], { version: 5 })); storageSlotsAfter = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlotsAfter.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV5.getAddress(), i)); } storageSlotsAfter = storageSlotsAfter.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // Check if storage slots are the same after upgrade for (let i = 0; i < storageSlots.length; i++) { // console.log("*** storageSlots v4", storageSlots[i], "vs v5", storageSlotsAfter[i]) (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfter[i]); } // Check if all GM NFTs are still owned by the original owners (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await owner.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await otherAccounts[6].getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(4)).to.equal(await otherAccounts[6].getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(5)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(6)).to.equal(await otherAccounts[6].getAddress()); // Check that existing GM NFTs have the same level (0, chai_1.expect)(await galaxyMemberV5.levelOf(1)).to.equal(7); (0, chai_1.expect)(await galaxyMemberV5.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.levelOf(4)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.levelOf(5)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.levelOf(6)).to.equal(1); // Mint a new GM NFT to owner await galaxyMemberV5.connect(owner).freeMint(); (0, chai_1.expect)(await galaxyMemberV5.balanceOf(await owner.getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(7)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV5.levelOf(7)).to.equal(1); // Earth // Check token selection (0, chai_1.expect)(await galaxyMemberV5.getSelectedTokenId(owner.getAddress())).to.equal(5n); (0, chai_1.expect)(await galaxyMemberV5.getSelectedTokenId(otherAccounts[6].getAddress())).to.equal(4n); // Can still check the level of the vechain node (0, chai_1.expect)(await galaxyMemberV5.getNodeLevelOf(nodeId)).to.equal(7); // The node is still attached to the GM NFT gmId1, resulting on the GM NFT having level 7 (0, chai_1.expect)(await galaxyMemberV5.getIdAttachedToNode(nodeId)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV5.levelOf(1)).to.equal(7); // Node can be delegated, and the GM will be downgraded await nodeManagement.connect(otherAccount).delegateNode(otherAccounts[1].address, nodeId); (0, chai_1.expect)(await galaxyMemberV5.levelOf(1)).to.equal(2); // Moon // For the record, otherAccounts[1] is the new delegatee/node manager, they also own GM NFT gmId3 (0, chai_1.expect)(await nodeManagement.getNodeManager(nodeId)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV5.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV5.levelOf(3)).to.equal(1); // Earth // Delegatee decides to attach the delegated node to their own GM NFT (need to detach first) await galaxyMemberV5.connect(otherAccounts[1]).detachNode(nodeId, 1); await galaxyMemberV5.connect(otherAccounts[1]).attachNode(nodeId, 3); (0, chai_1.expect)(await galaxyMemberV5.levelOf(3)).to.equal(7); // Saturn - the node gets a free upgrade // Node owner - otherAccount - who's nor the GM NFT owner neither the node manager - can still detach the node await galaxyMemberV5.connect(otherAccount).detachNode(nodeId, 3); (0, chai_1.expect)(await galaxyMemberV5.levelOf(3)).to.equal(1); // Back to Earth // after the upgrade, we check that the mapping _nodeToFreeUpgradeLevel has no corrupted values for (let i = 0; i < levels.length; i++) { const freeUpgradeLevel = await galaxyMemberV5.getNodeToFreeLevel(levels[i].id); (0, chai_1.expect)(freeUpgradeLevel).to.equal(freeUpgradeLevels[i]); } // we can add a new _nodeToFreeUpgradeLevel value await galaxyMemberV5.connect(owner).setNodeToFreeUpgradeLevel(9, 4); (0, chai_1.expect)(await galaxyMemberV5.getNodeToFreeLevel(9)).to.equal(4); // we can remove a _nodeToFreeUpgradeLevel value await galaxyMemberV5.connect(owner).setNodeToFreeUpgradeLevel(10, 6); (0, chai_1.expect)(await galaxyMemberV5.getNodeToFreeLevel(10)).to.equal(6); // we can update previous _nodeToFreeUpgradeLevel value await galaxyMemberV5.connect(owner).setNodeToFreeUpgradeLevel(1, 5); (0, chai_1.expect)(await galaxyMemberV5.getNodeToFreeLevel(1)).to.equal(5); // validate again that we can fetch the correct values for (let i = 0; i < levels.length; i++) { const freeUpgradeLevel = await galaxyMemberV5.getNodeToFreeLevel(levels[i].id); // we changed the above levels above, so adding if conditions so we can reuse the preiovious array if (levels[i].id === 1n) { (0, chai_1.expect)(freeUpgradeLevel).to.equal(5); } else if (levels[i].id === 10n) { (0, chai_1.expect)(freeUpgradeLevel).to.equal(6); } else if (levels[i].id === 9n) { (0, chai_1.expect)(freeUpgradeLevel).to.equal(4); } else { (0, chai_1.expect)(freeUpgradeLevel).to.equal(freeUpgradeLevels[i]); } } storageSlots = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlots.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV5.getAddress(), i)); } storageSlots = storageSlots.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); //-------------------------------- ⚠️ IMPORTANT ⚠️ -------------------------------- // NODE OWNER (otherAccount) MUST MIGRATE NODE TO STARGATE BEFORE UPGRADING TO V6 // Otherwise galaxy member will be "reset" for users with gm attached to legacy nodes //-------------------------------- ⚠️ IMPORTANT ⚠️ -------------------------------- //Admin updates lead time on Legacy Token Auction const setLeadTimeTx = await vechainNodes.setLeadTime(0); await setLeadTimeTx.wait(); await stargateMock .connect(otherAccount) .migrate(nodeId, { value: (await stargateNftMock.getLevel(7)).vetAmountRequiredToStake, gasLimit: 10000000 }); const galaxyMemberV6 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV5", "GalaxyMember", await galaxyMember.getAddress(), [await stargateNftMock.getAddress()], { version: 6, })); (0, chai_1.expect)(await galaxyMemberV6.version()).to.equal("6"); storageSlotsAfter = []; for (let i = initialSlot; i < initialSlot + BigInt(100); i++) { storageSlotsAfter.push(await hardhat_1.ethers.provider.getStorage(await galaxyMemberV6.getAddress(), i)); } storageSlotsAfter = storageSlotsAfter.filter(slot => slot !== "0x0000000000000000000000000000000000000000000000000000000000000000"); // Check if storage slots are the same after upgrade for (let i = 0; i < storageSlots.length; i++) { // console.log("*** storageSlots v5", storageSlots[i], "vs v6", storageSlotsAfter[i]) (0, chai_1.expect)(storageSlots[i]).to.equal(storageSlotsAfter[i]); } // Check if all GM NFTs are still owned by the original owners (0, chai_1.expect)(await galaxyMemberV6.balanceOf(await owner.getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV6.balanceOf(await otherAccount.getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.balanceOf(await otherAccounts[0].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.balanceOf(await otherAccounts[1].getAddress())).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.balanceOf(await otherAccounts[6].getAddress())).to.equal(2); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(1)).to.equal(await otherAccount.getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(2)).to.equal(await otherAccounts[0].getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(3)).to.equal(await otherAccounts[1].getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(4)).to.equal(await otherAccounts[6].getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(5)).to.equal(await owner.getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(6)).to.equal(await otherAccounts[6].getAddress()); (0, chai_1.expect)(await galaxyMemberV6.ownerOf(7)).to.equal(await owner.getAddress()); // Check that existing GM NFTs have the same level (0, chai_1.expect)(await galaxyMemberV6.levelOf(1)).to.equal(2); // Moon (node was detached at line 657) (0, chai_1.expect)(await galaxyMemberV6.levelOf(2)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(3)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(4)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(5)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(6)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(7)).to.equal(1); // Check token selection (0, chai_1.expect)(await galaxyMemberV6.getSelectedTokenId(owner.getAddress())).to.equal(5n); (0, chai_1.expect)(await galaxyMemberV6.getSelectedTokenId(otherAccounts[6].getAddress())).to.equal(4n); // Can still check the level of the vechain node (0, chai_1.expect)(await galaxyMemberV6.getNodeLevelOf(nodeId)).to.equal(7); // The node is no longer attached to any GM NFT (was detached at line 657) (0, chai_1.expect)(await galaxyMemberV6.getIdAttachedToNode(nodeId)).to.equal(0); // Attach the node back to gmId 1 await galaxyMemberV6.connect(otherAccount).attachNode(nodeId, 1); (0, chai_1.expect)(await galaxyMemberV6.levelOf(1)).to.equal(7); // Saturn (0, chai_1.expect)(await galaxyMemberV6.getIdAttachedToNode(nodeId)).to.equal(1); }); it("Should reset attachment if node NOT migrated before upgrading to V6", async () => { // Bootstrap emissions await (0, common_1.bootstrapEmissions)(); const galaxyMemberV1 = (await (0, helpers_2.deployProxy)("GalaxyMemberV1", [ { name: helpers_1.NFT_NAME, symbol: helpers_1.NFT_SYMBOL, admin: owner.address, upgrader: owner.address, pauser: owner.address, minter: owner.address, contractsAddressManager: owner.address, maxLevel: 5, baseTokenURI: config.GM_NFT_BASE_URI, b3trToUpgradeToLevel: config.GM_NFT_B3TR_REQUIRED_TO_UPGRADE_TO_LEVEL, b3tr: await b3tr.getAddress(), treasury: await treasury.getAddress(), }, ])); await galaxyMemberV1.waitForDeployment(); (0, chai_1.expect)(await galaxyMemberV1.MAX_LEVEL()).to.equal(5); await galaxyMemberV1.connect(owner).setXAllocationsGovernorAddress(await xAllocationVoting.getAddress()); await galaxyMemberV1.connect(owner).setB3trGovernorAddress(await governor.getAddress()); //Participate in governance - owner needs to participate to be able to free mint await (0, common_1.participateInAllocationVoting)(owner, true, otherAccounts[10]); //Mint 4 tokens to owner await galaxyMemberV1.connect(owner).freeMint(); // gmId 0 await galaxyMemberV1.connect(owner).burn(0); // gmId 0 await galaxyMemberV1.connect(owner).freeMint(); // gmId 1 await galaxyMemberV1.connect(owner).burn(1); // gmId 1 await galaxyMemberV1.connect(owner).freeMint(); // gmId 2 await galaxyMemberV1.connect(owner).burn(2); // gmId 2 await galaxyMemberV1.connect(owner).freeMint(); // gmId 3 await galaxyMemberV1.connect(owner).burn(3); // gmId 3 //Upgrade to v2 const galaxyMemberV2 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV1", "GalaxyMemberV2", await galaxyMemberV1.getAddress(), [owner.address, await nodeManagement.getAddress(), owner.address, config.GM_NFT_NODE_TO_FREE_LEVEL], { version: 2 })); (0, chai_1.expect)(await galaxyMemberV2.version()).to.equal("2"); //Upgrade to v3 const galaxyMemberV3 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV2", "GalaxyMemberV3", await galaxyMemberV2.getAddress(), [], { version: 3 })); (0, chai_1.expect)(await galaxyMemberV3.version()).to.equal("3"); //Upgrade to v4 const galaxyMemberV4 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV3", "GalaxyMemberV4", await galaxyMemberV3.getAddress(), [], { version: 4 })); (0, chai_1.expect)(await galaxyMemberV4.version()).to.equal("4"); //Upgrade to v5 const galaxyMemberV5 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV4", "GalaxyMemberV5", await galaxyMemberV4.getAddress(), [], { version: 5 })); (0, chai_1.expect)(await galaxyMemberV5.version()).to.equal("5"); const gmId = 4; await galaxyMemberV5.connect(owner).freeMint(); //gmid 4 await (0, common_1.mintLegacyNode)(7, owner); const ownerNodes = await nodeManagement.getUserNodes(owner.address); const nodeId = ownerNodes[0].nodeId; await galaxyMemberV5.connect(owner).attachNode(nodeId, gmId); //Upgrade to v6 const galaxyMemberV6 = (await (0, helpers_2.upgradeProxy)("GalaxyMemberV5", "GalaxyMember", await galaxyMemberV5.getAddress(), [await stargateNftMock.getAddress()], { version: 6 })); (0, chai_1.expect)(await galaxyMemberV6.version()).to.equal("6"); (0, chai_1.expect)(await galaxyMemberV6.levelOf(gmId)).to.equal(1); (0, chai_1.expect)(await galaxyMemberV6.getIdAttachedToNode(nodeId)).to.equal(0); }); });