UNPKG

@vechain/vebetterdao-contracts

Version:

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

837 lines 114 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const mocha_1 = require("mocha"); const helpers_1 = require("./helpers"); const chai_1 = require("chai"); const hardhat_1 = require("hardhat"); const allocations_1 = require("./helpers/allocations"); const local_1 = require("@repo/config/contracts/envs/local"); const config_1 = require("./helpers/config"); const generateB3trAllocations_1 = require("./helpers/generateB3trAllocations"); const upgrades_core_1 = require("@openzeppelin/upgrades-core"); const helpers_2 = require("../scripts/helpers"); const full_allocations_round_14_decay_json_1 = __importDefault(require("./fixture/full-allocations-round-14-decay.json")); const updated_full_allocations_with_gm_json_1 = __importDefault(require("./fixture/updated-full-allocations-with-gm.json")); (0, mocha_1.describe)("Emissions - @shard2", () => { (0, mocha_1.describe)("Contract parameters", () => { (0, mocha_1.it)("Should have correct parameters set on deployment", async () => { const config = (0, local_1.createLocalConfig)(); const { emissions, owner, b3tr, minterAccount, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); // Destination addresses should be set correctly (0, chai_1.expect)(await emissions.xAllocations()).to.equal(await xAllocationPool.getAddress()); (0, chai_1.expect)(await emissions.vote2Earn()).to.equal(await voterRewards.getAddress()); (0, chai_1.expect)(await emissions.treasury()).to.equal(await treasury.getAddress()); // Admin should be set correctly (0, chai_1.expect)(await emissions.hasRole(await emissions.DEFAULT_ADMIN_ROLE(), await owner.getAddress())).to.equal(true); // Minter should be set correctly (0, chai_1.expect)(await emissions.hasRole(await emissions.MINTER_ROLE(), await minterAccount.getAddress())).to.equal(true); // Initial allocation amounts should be set correctly const initialEmissions = await emissions.initialXAppAllocation(); (0, chai_1.expect)(initialEmissions).to.equal(config.INITIAL_X_ALLOCATION); // B3TR address should be set correctly (0, chai_1.expect)(await emissions.b3tr()).to.equal(await b3tr.getAddress()); // Decay settings should be set correctly (0, chai_1.expect)(await emissions.xAllocationsDecay()).to.equal(config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE); (0, chai_1.expect)(await emissions.vote2EarnDecay()).to.equal(config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE); (0, chai_1.expect)(await emissions.xAllocationsDecayPeriod()).to.equal(config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD); (0, chai_1.expect)(await emissions.vote2EarnDecayPeriod()).to.equal(config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD); // Treasury percentage should be set correctly (0, chai_1.expect)(await emissions.treasuryPercentage()).to.equal(config.EMISSIONS_TREASURY_PERCENTAGE); // GM Percentage of Treasury Pool should be set correctly (0, chai_1.expect)(await emissions.gmPercentage()).to.equal(config.GM_PERCENTAGE_OF_TREASURY); }); (0, mocha_1.it)("Should revert if Treasury is set to zero address in initilisation", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, minterAccount, xAllocationPool, voterRewards } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), helpers_1.ZERO_ADDRESS, config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should revert if XAllocations is set to zero address in initilisation", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, minterAccount, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ helpers_1.ZERO_ADDRESS, await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should revert if vote2Earn is set to zero address in initilisation", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, minterAccount, xAllocationPool, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), helpers_1.ZERO_ADDRESS, await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should revert if admin is set to zero address in initilisation", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, minterAccount, xAllocationPool, treasury, voterRewards } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: helpers_1.ZERO_ADDRESS, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should revert if Treasury is set to zero address in initilisation", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, minterAccount, xAllocationPool, voterRewards } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), helpers_1.ZERO_ADDRESS, config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should be able to change the X allocations address", async () => { const { emissions, otherAccounts, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(emissions.connect(owner).setXallocationsAddress(helpers_1.ZERO_ADDRESS)).to.be.reverted; const tx = await emissions.connect(owner).setXallocationsAddress(otherAccounts[3].address); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("XAllocationsAddressUpdated"); (0, chai_1.expect)(await emissions.xAllocations()).to.equal(otherAccounts[3].address); }); (0, mocha_1.it)("Should be able to change the Vote 2 Earn address", async () => { const { emissions, otherAccounts, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(emissions.connect(owner).setVote2EarnAddress(helpers_1.ZERO_ADDRESS)).to.be.reverted; await (0, chai_1.expect)(emissions.connect(otherAccount).setVote2EarnAddress(otherAccounts[3].address)).to.be.reverted; // Not admin const tx = await emissions.connect(owner).setVote2EarnAddress(otherAccounts[3].address); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("Vote2EarnAddressUpdated"); (0, chai_1.expect)(await emissions.vote2Earn()).to.equal(otherAccounts[3].address); }); (0, mocha_1.it)("Should be able to change the Treasury address", async () => { const { emissions, otherAccounts, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(emissions.connect(owner).setTreasuryAddress(helpers_1.ZERO_ADDRESS)).to.be.reverted; await (0, chai_1.expect)(emissions.connect(otherAccount).setTreasuryAddress(otherAccounts[3].address)).to.be.reverted; // Not admin const tx = await emissions.connect(owner).setTreasuryAddress(otherAccounts[3].address); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("TreasuryAddressUpdated"); (0, chai_1.expect)(await emissions.treasury()).to.equal(otherAccounts[3].address); }); (0, mocha_1.it)("Should not be able to change the X allocations address if not admin", async () => { const { emissions, otherAccounts } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(otherAccounts[0]).setXallocationsAddress(otherAccounts[3].address)); }); (0, mocha_1.it)("Treasury percentage should be between 0 and 10000", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(owner).setTreasuryPercentage(10001)); try { await emissions.connect(owner).setTreasuryPercentage(-1); chai_1.assert.fail("Should revert"); } catch (e) { /* empty */ } await emissions.connect(owner).setTreasuryPercentage(10000); await emissions.connect(owner).setTreasuryPercentage(0); const tx = await emissions.connect(owner).setTreasuryPercentage(550); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("TreasuryPercentageUpdated"); await (0, chai_1.expect)(emissions.connect(otherAccount).setTreasuryPercentage(55)).to.be.reverted; // Not admin }); (0, mocha_1.it)("GM Percentage of Treasury Pool should be between 0 and 10000", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(owner).setGmPercentage(10001)); try { await emissions.connect(owner).setGmPercentage(-1); chai_1.assert.fail("Should revert"); } catch (e) { /* empty */ } await emissions.connect(owner).setGmPercentage(10000); await emissions.connect(owner).setGmPercentage(0); const tx = await emissions.connect(owner).setGmPercentage(550); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("GMPercentageUpdated"); await (0, chai_1.expect)(emissions.connect(otherAccount).setGmPercentage(55)).to.be.reverted; // Not admin }); (0, mocha_1.it)("MaxVote2EarnDecay percentage should be between 0 and 100", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(owner).setMaxVote2EarnDecay(101)); try { await emissions.connect(owner).setMaxVote2EarnDecay(-1); chai_1.assert.fail("Should revert"); } catch (e) { /* empty */ } await emissions.connect(owner).setMaxVote2EarnDecay(100); await emissions.connect(owner).setMaxVote2EarnDecay(0); const tx = await emissions.connect(owner).setMaxVote2EarnDecay(55); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("MaxVote2EarnDecayUpdated"); await (0, chai_1.expect)(emissions.connect(otherAccount).setMaxVote2EarnDecay(55)).to.be.reverted; // Not admin }); (0, mocha_1.it)("Vote2EarnDecay percentage should be between 0 and 100", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(owner).setVote2EarnDecay(101)); try { await emissions.connect(owner).setVote2EarnDecay(-1); chai_1.assert.fail("Should revert"); } catch (e) { /* empty */ } await emissions.connect(owner).setVote2EarnDecay(100); await emissions.connect(owner).setVote2EarnDecay(0); const tx = await emissions.connect(owner).setVote2EarnDecay(55); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("Vote2EarnDecayUpdated"); await (0, chai_1.expect)(emissions.connect(otherAccount).setVote2EarnDecay(55)).to.be.reverted; // Not admin }); (0, mocha_1.it)("XAllocationsDecay percentage should be between 0 and 100", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(emissions.connect(owner).setXAllocationsDecay(101)); try { await emissions.connect(owner).setXAllocationsDecay(-1); chai_1.assert.fail("Should revert"); } catch (e) { /* empty */ } await emissions.connect(owner).setXAllocationsDecay(100); await emissions.connect(owner).setXAllocationsDecay(0); const tx = await emissions.connect(owner).setXAllocationsDecay(55); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("XAllocationsDecayUpdated"); await (0, chai_1.expect)(emissions.connect(otherAccount).setXAllocationsDecay(55)).to.be.reverted; // Not admin }); (0, mocha_1.it)("Should return correct x allocations governor address", async () => { const { emissions, xAllocationVoting } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await emissions.xAllocationsGovernor()).to.equal(await xAllocationVoting.getAddress()); }); (0, mocha_1.it)("Should return max vote 2 earn decay percentage", async () => { const { emissions } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await emissions.maxVote2EarnDecay()).to.equal(80); }); (0, mocha_1.it)("Should return scaling factor", async () => { const { emissions } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await emissions.SCALING_FACTOR()).to.equal(10 ** 6); }); (0, mocha_1.it)("Should be able to change cycle duration", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); const tx = await emissions.connect(owner).setCycleDuration(1000); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("EmissionCycleDurationUpdated"); (0, chai_1.expect)(await emissions.cycleDuration()).to.equal(1000); await (0, chai_1.expect)(emissions.connect(otherAccount).setCycleDuration(1000)).to.be.reverted; // Not admin await (0, chai_1.expect)(emissions.connect(owner).setCycleDuration(0)).to.be.reverted; // At least 1 block }); (0, mocha_1.it)("Should revert if cycle period is set less than voting period", async () => { const { emissions, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(emissions.connect(owner).setCycleDuration(10)).to.be.reverted; }); (0, mocha_1.it)("Should be able to change x allocations decay period", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); const tx = await emissions.connect(owner).setXAllocationsDecayPeriod(1000); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("XAllocationsDecayPeriodUpdated"); (0, chai_1.expect)(await emissions.xAllocationsDecayPeriod()).to.equal(1000); await (0, chai_1.expect)(emissions.connect(otherAccount).setXAllocationsDecayPeriod(1000)).to.be.reverted; // Not admin await (0, chai_1.expect)(emissions.connect(owner).setXAllocationsDecayPeriod(0)).to.be.reverted; // At least 1 block }); (0, mocha_1.it)("Should be able to change vote 2 earn decay period", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); const tx = await emissions.connect(owner).setVote2EarnDecayPeriod(1000); const receipt = await tx.wait(); const eventName = (0, helpers_1.getEventName)(receipt, emissions); (0, chai_1.expect)(eventName).to.equal("Vote2EarnDecayPeriodUpdated"); (0, chai_1.expect)(await emissions.vote2EarnDecayPeriod()).to.equal(1000); await (0, chai_1.expect)(emissions.connect(otherAccount).setVote2EarnDecayPeriod(1000)).to.be.reverted; // Not admin await (0, chai_1.expect)(emissions.connect(owner).setVote2EarnDecayPeriod(0)).to.be.reverted; // At least 1 block }); (0, mocha_1.it)("Should be able to change x allocations voting governor", async () => { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(emissions.connect(otherAccount).setXAllocationsGovernorAddress(otherAccount.address)).to.be.reverted; // Not admin await (0, chai_1.expect)(emissions.connect(owner).setXAllocationsGovernorAddress(helpers_1.ZERO_ADDRESS)).to.be.reverted; // Can't be zero address }); // it("getScaledDecayPercentage: decay percentage should be between 0 and 99", async () => { // const { emissions, owner } = await getOrDeployContractInstances({ // forceDeploy: true, // }) // await expect(emissions.connect(owner).getScaledDecayPercentage(101)).to.be.reverted // try { // await emissions.connect(owner).getScaledDecayPercentage(-1) // assert.fail("Should revert") // } catch (e) { // /* empty */ // } // await expect(emissions.connect(owner).getScaledDecayPercentage(100)).to.be.reverted // await expect(emissions.connect(owner).getScaledDecayPercentage(0)).not.to.be.reverted // await expect(emissions.connect(owner).getScaledDecayPercentage(55)).not.to.be.reverted // }) }); (0, mocha_1.describe)("Contract upgradeablity", () => { (0, mocha_1.it)("Admin should be able to upgrade the contract", async function () { const { emissions, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("Emissions"); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.getAddress()); const UPGRADER_ROLE = await emissions.UPGRADER_ROLE(); (0, chai_1.expect)(await emissions.hasRole(UPGRADER_ROLE, owner.address)).to.eql(true); await (0, chai_1.expect)(emissions.connect(owner).upgradeToAndCall(await implementation.getAddress(), "0x")).to.not.be .reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.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 admin should be able to upgrade the contract", async function () { const { emissions, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("Emissions"); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.getAddress()); const UPGRADER_ROLE = await emissions.UPGRADER_ROLE(); (0, chai_1.expect)(await emissions.hasRole(UPGRADER_ROLE, otherAccount.address)).to.eql(false); await (0, chai_1.expect)(emissions.connect(otherAccount).upgradeToAndCall(await implementation.getAddress(), "0x")).to.be .reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.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)("Admin can change UPGRADER_ROLE", async function () { const { emissions, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("Emissions"); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.getAddress()); const UPGRADER_ROLE = await emissions.UPGRADER_ROLE(); (0, chai_1.expect)(await emissions.hasRole(UPGRADER_ROLE, otherAccount.address)).to.eql(false); await (0, chai_1.expect)(emissions.connect(owner).grantRole(UPGRADER_ROLE, otherAccount.address)).to.not.be.reverted; await (0, chai_1.expect)(emissions.connect(owner).revokeRole(UPGRADER_ROLE, owner.address)).to.not.be.reverted; await (0, chai_1.expect)(emissions.connect(otherAccount).upgradeToAndCall(await implementation.getAddress(), "0x")).to.not.be .reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await emissions.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)("Should not be able to call initializer after deployment", async () => { const config = (0, local_1.createLocalConfig)(); const { emissions, owner, minterAccount, xAllocationPool, voterRewards, treasury, b3tr } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); (0, chai_1.expect)(emissions.initialize({ minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: 0, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, })).to.be.reverted; (0, chai_1.expect)(emissions.initializeV3(config.GM_PERCENTAGE_OF_TREASURY)).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with initial X Allocations zero", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: 0, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with cycle duration less or equal to 0", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: 0, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with treasury percentage not between 1 and 10000", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: 0, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to upgrade with GM percentage not between 1 and 10000", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); const emissions = (await (0, helpers_2.deployAndUpgrade)(["EmissionsV1", "EmissionsV2"], [ [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ], [], ], { versions: [undefined, 2], logOutput: false, })); await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("EmissionsV2", "Emissions", await emissions.getAddress(), [10001], { version: 3, })).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with x allocations decay percentage not between 1 and 100", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ 101, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with vote2Earn decay percentage not between 1 and 100", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, 0, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with xAllocations decay delay period less than 1", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, 0, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with vote2Earn decay delay period less than 1", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, 0, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: config.EMISSIONS_MAX_VOTE_2_EARN_DECAY_PERCENTAGE, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should not be able to deploy with max vote2Earn decay percentage not between 1 and 100", async () => { const config = (0, config_1.createTestConfig)(); const { owner, minterAccount, b3tr, xAllocationPool, voterRewards, treasury } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("Emissions", [ { minter: minterAccount.address, admin: owner.address, upgrader: owner.address, contractsAddressManager: owner.address, decaySettingsManager: owner.address, b3trAddress: await b3tr.getAddress(), destinations: [ await xAllocationPool.getAddress(), await voterRewards.getAddress(), await treasury.getAddress(), config.MIGRATION_ADDRESS, ], initialXAppAllocation: config.INITIAL_X_ALLOCATION, cycleDuration: config.EMISSIONS_CYCLE_DURATION, decaySettings: [ config.EMISSIONS_X_ALLOCATION_DECAY_PERCENTAGE, config.EMISSIONS_VOTE_2_EARN_DECAY_PERCENTAGE, config.EMISSIONS_X_ALLOCATION_DECAY_PERIOD, config.EMISSIONS_VOTE_2_EARN_ALLOCATION_DECAY_PERIOD, ], treasuryPercentage: config.EMISSIONS_TREASURY_PERCENTAGE, maxVote2EarnDecay: 0, migrationAmount: config.MIGRATION_AMOUNT, }, ])).to.be.reverted; }); (0, mocha_1.it)("Should return correct version of the contract", async () => { const { emissions } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await emissions.version()).