@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
JavaScript
"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()).