@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
JavaScript
"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);
});
});