UNPKG

@vechain/vebetterdao-contracts

Version:

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

708 lines 163 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const hardhat_1 = require("hardhat"); const chai_1 = require("chai"); const helpers_1 = require("./helpers"); const mocha_1 = require("mocha"); const upgrades_core_1 = require("@openzeppelin/upgrades-core"); const helpers_2 = require("../scripts/helpers"); const xnodes_1 = require("./helpers/xnodes"); const local_1 = require("@repo/config/contracts/envs/local"); (0, mocha_1.describe)("X2EarnRewardsPool - @shard12", function () { // Environment params let creator1; let creator2; (0, mocha_1.before)(async function () { const { creators } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true }); creator1 = creators[0]; creator2 = creators[1]; }); // deployment (0, mocha_1.describe)("Deployment", function () { (0, mocha_1.it)("Cannot deploy contract with zero address", async function () { const { owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); await (0, chai_1.expect)((0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [owner.address, owner.address, owner.address, owner.address, helpers_1.ZERO_ADDRESS])).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [owner.address, owner.address, owner.address, helpers_1.ZERO_ADDRESS, owner.address])).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [owner.address, owner.address, helpers_1.ZERO_ADDRESS, owner.address, owner.address])).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [owner.address, helpers_1.ZERO_ADDRESS, owner.address, owner.address, owner.address])).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [helpers_1.ZERO_ADDRESS, owner.address, owner.address, owner.address, owner.address])).to.be.reverted; }); (0, mocha_1.it)("Should deploy the contract", async function () { const { x2EarnRewardsPool } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true }); (0, chai_1.expect)(await x2EarnRewardsPool.getAddress()).to.not.equal(helpers_1.ZERO_ADDRESS); }); (0, mocha_1.it)("Should set B3TR correctly", async function () { const { x2EarnRewardsPool, b3tr } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false }); (0, chai_1.expect)(await x2EarnRewardsPool.b3tr()).to.equal(await b3tr.getAddress()); }); (0, mocha_1.it)("Version should be set correctly", async function () { const { x2EarnRewardsPool } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); (0, chai_1.expect)(await x2EarnRewardsPool.version()).to.equal("8"); }); (0, mocha_1.it)("X2EarnApps should be set correctly", async function () { const { x2EarnRewardsPool, x2EarnApps } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false }); (0, chai_1.expect)(await x2EarnRewardsPool.x2EarnApps()).to.equal(await x2EarnApps.getAddress()); }); }); // upgradeability (0, mocha_1.describe)("Contract upgradeablity", () => { (0, mocha_1.it)("Cannot initialize twice", async function () { const { owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, owner.address, owner.address, ])); await (0, helpers_1.catchRevert)(x2EarnRewardsPoolV1.initialize(owner.address, owner.address, owner.address, owner.address, owner.address)); }); (0, mocha_1.it)("User with UPGRADER_ROLE should be able to upgrade the contract", async function () { const { x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("X2EarnRewardsPoolV1"); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnRewardsPool.getAddress()); const UPGRADER_ROLE = await x2EarnRewardsPool.UPGRADER_ROLE(); (0, chai_1.expect)(await x2EarnRewardsPool.hasRole(UPGRADER_ROLE, owner.address)).to.eql(true); await (0, chai_1.expect)(x2EarnRewardsPool.connect(owner).upgradeToAndCall(await implementation.getAddress(), "0x")).to.not.be .reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnRewardsPool.getAddress()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.not.eql(currentImplAddress.toUpperCase()); (0, chai_1.expect)(newImplAddress.toUpperCase()).to.eql((await implementation.getAddress()).toUpperCase()); }); (0, mocha_1.it)("Only user with UPGRADER_ROLE should be able to upgrade the contract", async function () { const { x2EarnRewardsPool, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); // Deploy the implementation contract const Contract = await hardhat_1.ethers.getContractFactory("X2EarnRewardsPoolV1"); const implementation = await Contract.deploy(); await implementation.waitForDeployment(); const currentImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnRewardsPool.getAddress()); const UPGRADER_ROLE = await x2EarnRewardsPool.UPGRADER_ROLE(); (0, chai_1.expect)(await x2EarnRewardsPool.hasRole(UPGRADER_ROLE, otherAccount.address)).to.eql(false); await (0, chai_1.expect)(x2EarnRewardsPool.connect(otherAccount).upgradeToAndCall(await implementation.getAddress(), "0x")).to .be.reverted; const newImplAddress = await (0, upgrades_core_1.getImplementationAddress)(hardhat_1.ethers.provider, await x2EarnRewardsPool.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)("Should return correct version of the contract", async () => { const { x2EarnRewardsPool } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await x2EarnRewardsPool.version()).to.equal("8"); }); (0, mocha_1.it)("Storage should be preserved after upgrade", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, x2EarnApps, minterAccount, veBetterPassport } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, await b3tr.getAddress(), await x2EarnApps.getAddress(), ])); (0, chai_1.expect)(await x2EarnRewardsPoolV1.version()).to.equal("1"); // update x2EarnApps address await x2EarnRewardsPoolV1.connect(owner).setX2EarnApps(await x2EarnApps.getAddress()); const x2EarnAppsAddress = await x2EarnRewardsPoolV1.x2EarnApps(); // deposit some funds const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app"), creator1); await x2EarnApps.connect(creator2).submitApp(owner.address, owner.address, "My app #2", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app #2"), creator2); await b3tr.connect(owner).approve(await x2EarnRewardsPoolV1.getAddress(), amount); await x2EarnRewardsPoolV1.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPoolV1.getAddress())).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV2 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, config.X_2_EARN_INITIAL_IMPACT_KEYS], { version: 2, })); (0, chai_1.expect)(await x2EarnRewardsPoolV2.version()).to.equal("2"); (0, chai_1.expect)(await x2EarnRewardsPoolV2.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV2.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV3 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV2", "X2EarnRewardsPoolV3", await x2EarnRewardsPoolV1.getAddress(), [await veBetterPassport.getAddress()], { version: 3, })); (0, chai_1.expect)(await x2EarnRewardsPoolV3.version()).to.equal("3"); (0, chai_1.expect)(await x2EarnRewardsPoolV3.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV3.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV4 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV3", "X2EarnRewardsPoolV4", await x2EarnRewardsPoolV1.getAddress(), [], { version: 4, })); (0, chai_1.expect)(await x2EarnRewardsPoolV4.version()).to.equal("4"); (0, chai_1.expect)(await x2EarnRewardsPoolV4.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV4.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV5 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV4", "X2EarnRewardsPoolV5", await x2EarnRewardsPoolV1.getAddress(), [], { version: 5, })); (0, chai_1.expect)(await x2EarnRewardsPoolV5.version()).to.equal("5"); (0, chai_1.expect)(await x2EarnRewardsPoolV5.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV5.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV6 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV5", "X2EarnRewardsPoolV6", await x2EarnRewardsPoolV1.getAddress(), [], { version: 6, })); (0, chai_1.expect)(await x2EarnRewardsPoolV6.version()).to.equal("6"); (0, chai_1.expect)(await x2EarnRewardsPoolV6.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV6.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to V7 const x2EarnRewardsPoolV7 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV6", "X2EarnRewardsPoolV7", await x2EarnRewardsPoolV1.getAddress(), [], { version: 7, })); (0, chai_1.expect)(await x2EarnRewardsPoolV7.version()).to.equal("7"); // upgrade to V8 const x2EarnRewardsPool = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV7", "X2EarnRewardsPool", await x2EarnRewardsPoolV1.getAddress(), [], { version: 8, })); (0, chai_1.expect)(await x2EarnRewardsPool.version()).to.equal("8"); (0, chai_1.expect)(await x2EarnRewardsPool.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPool.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); }); (0, mocha_1.it)("Should be able to distribute rewards without providing metadata", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, x2EarnApps, minterAccount, veBetterPassport, otherAccounts } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, await b3tr.getAddress(), await x2EarnApps.getAddress(), ])); (0, chai_1.expect)(await x2EarnRewardsPoolV1.version()).to.equal("1"); // update x2EarnApps address await x2EarnRewardsPoolV1.connect(owner).setX2EarnApps(await x2EarnApps.getAddress()); const x2EarnAppsAddress = await x2EarnRewardsPoolV1.x2EarnApps(); // deposit some funds const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app"), creator1); await x2EarnApps.connect(creator2).submitApp(owner.address, owner.address, "My app #2", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app #2"), creator2); await b3tr.connect(owner).approve(await x2EarnRewardsPoolV1.getAddress(), amount); await x2EarnRewardsPoolV1.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPoolV1.getAddress())).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV2 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, config.X_2_EARN_INITIAL_IMPACT_KEYS], { version: 2, })); (0, chai_1.expect)(await x2EarnRewardsPoolV2.version()).to.equal("2"); (0, chai_1.expect)(await x2EarnRewardsPoolV2.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV2.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV3 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV2", "X2EarnRewardsPoolV3", await x2EarnRewardsPoolV1.getAddress(), [await veBetterPassport.getAddress()], { version: 3, })); (0, chai_1.expect)(await x2EarnRewardsPoolV3.version()).to.equal("3"); (0, chai_1.expect)(await x2EarnRewardsPoolV3.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV3.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV4 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV3", "X2EarnRewardsPoolV4", await x2EarnRewardsPoolV1.getAddress(), [], { version: 4, })); (0, chai_1.expect)(await x2EarnRewardsPoolV4.version()).to.equal("4"); (0, chai_1.expect)(await x2EarnRewardsPoolV4.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV4.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV5 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV4", "X2EarnRewardsPoolV5", await x2EarnRewardsPoolV1.getAddress(), [], { version: 5, })); (0, chai_1.expect)(await x2EarnRewardsPoolV5.version()).to.equal("5"); (0, chai_1.expect)(await x2EarnRewardsPoolV5.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV5.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV6 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV5", "X2EarnRewardsPoolV6", await x2EarnRewardsPoolV1.getAddress(), [], { version: 6, })); (0, chai_1.expect)(await x2EarnRewardsPoolV6.version()).to.equal("6"); (0, chai_1.expect)(await x2EarnRewardsPoolV6.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV6.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to V7 const x2EarnRewardsPoolV7 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV6", "X2EarnRewardsPoolV7", await x2EarnRewardsPoolV1.getAddress(), [], { version: 7, })); (0, chai_1.expect)(await x2EarnRewardsPoolV7.version()).to.equal("7"); // upgrade to V8 const x2EarnRewardsPool = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV7", "X2EarnRewardsPool", await x2EarnRewardsPoolV1.getAddress(), [], { version: 8, })); (0, chai_1.expect)(await x2EarnRewardsPool.version()).to.equal("8"); (0, chai_1.expect)(await x2EarnRewardsPool.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPool.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); const user = otherAccounts[12]; await b3tr.connect(minterAccount).mint(owner.address, amount); const appId = await x2EarnApps.hashAppName("My app"); // add reward distributor await x2EarnApps.connect(owner).addRewardDistributor(appId, owner.address); (0, chai_1.expect)(await x2EarnApps.isRewardDistributor(appId, owner.address)).to.equal(true); // distribute reward const tx = await x2EarnRewardsPool .connect(owner) .distributeRewardWithProof(appId, hardhat_1.ethers.parseEther("1"), user.address, ["image"], ["https://image.png"], ["carbon", "water"], [100, 200], "The description of the action"); const receipt = await tx.wait(); (0, chai_1.expect)(await b3tr.balanceOf(user.address)).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPool.getAddress())).to.equal(hardhat_1.ethers.parseEther("99")); // event emitted if (!receipt) throw new Error("No receipt"); let event = (0, helpers_1.filterEventsByName)(receipt.logs, "RewardDistributed"); (0, chai_1.expect)(event).not.to.eql([]); (0, chai_1.expect)(event[0].args[0]).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(event[0].args[1]).to.equal(appId); (0, chai_1.expect)(event[0].args[2]).to.equal(user.address); const emittedProof = JSON.parse(event[0].args[3]); (0, chai_1.expect)(emittedProof).to.have.property("version"); (0, chai_1.expect)(emittedProof.version).to.equal(2); (0, chai_1.expect)(emittedProof).to.have.deep.property("proof", { image: "https://image.png" }); (0, chai_1.expect)(emittedProof).to.have.property("description"); (0, chai_1.expect)(emittedProof.description).to.equal("The description of the action"); (0, chai_1.expect)(emittedProof).to.have.deep.property("impact", { carbon: 100, water: 200 }); (0, chai_1.expect)(event[0].args[4]).to.equal(owner.address); }); (0, mocha_1.it)("Should be able to distribute rewards providing metadata", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, x2EarnApps, minterAccount, veBetterPassport, otherAccounts } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, await b3tr.getAddress(), await x2EarnApps.getAddress(), ])); (0, chai_1.expect)(await x2EarnRewardsPoolV1.version()).to.equal("1"); // update x2EarnApps address await x2EarnRewardsPoolV1.connect(owner).setX2EarnApps(await x2EarnApps.getAddress()); const x2EarnAppsAddress = await x2EarnRewardsPoolV1.x2EarnApps(); // deposit some funds const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app"), creator1); await x2EarnApps.connect(creator2).submitApp(owner.address, owner.address, "My app #2", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app #2"), creator2); await b3tr.connect(owner).approve(await x2EarnRewardsPoolV1.getAddress(), amount); await x2EarnRewardsPoolV1.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPoolV1.getAddress())).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV2 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, config.X_2_EARN_INITIAL_IMPACT_KEYS], { version: 2, })); (0, chai_1.expect)(await x2EarnRewardsPoolV2.version()).to.equal("2"); (0, chai_1.expect)(await x2EarnRewardsPoolV2.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV2.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV3 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV2", "X2EarnRewardsPoolV3", await x2EarnRewardsPoolV1.getAddress(), [await veBetterPassport.getAddress()], { version: 3, })); (0, chai_1.expect)(await x2EarnRewardsPoolV3.version()).to.equal("3"); (0, chai_1.expect)(await x2EarnRewardsPoolV3.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV3.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV4 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV3", "X2EarnRewardsPoolV4", await x2EarnRewardsPoolV1.getAddress(), [], { version: 4, })); (0, chai_1.expect)(await x2EarnRewardsPoolV4.version()).to.equal("4"); (0, chai_1.expect)(await x2EarnRewardsPoolV4.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV4.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV5 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV4", "X2EarnRewardsPoolV5", await x2EarnRewardsPoolV1.getAddress(), [], { version: 5, })); (0, chai_1.expect)(await x2EarnRewardsPoolV5.version()).to.equal("5"); (0, chai_1.expect)(await x2EarnRewardsPoolV5.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV5.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to new version const x2EarnRewardsPoolV6 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV5", "X2EarnRewardsPoolV6", await x2EarnRewardsPoolV1.getAddress(), [], { version: 6, })); (0, chai_1.expect)(await x2EarnRewardsPoolV6.version()).to.equal("6"); (0, chai_1.expect)(await x2EarnRewardsPoolV6.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPoolV6.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); // upgrade to V7 const x2EarnRewardsPoolV7 = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV6", "X2EarnRewardsPoolV7", await x2EarnRewardsPoolV1.getAddress(), [], { version: 7, })); (0, chai_1.expect)(await x2EarnRewardsPoolV7.version()).to.equal("7"); // upgrade to V8 const x2EarnRewardsPool = (await (0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV7", "X2EarnRewardsPool", await x2EarnRewardsPoolV1.getAddress(), [], { version: 8, })); (0, chai_1.expect)(await x2EarnRewardsPool.version()).to.equal("8"); (0, chai_1.expect)(await x2EarnRewardsPool.x2EarnApps()).to.equal(x2EarnAppsAddress); (0, chai_1.expect)(await x2EarnRewardsPool.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); const user = otherAccounts[12]; await b3tr.connect(minterAccount).mint(owner.address, amount); const appId = await x2EarnApps.hashAppName("My app"); // add reward distributor await x2EarnApps.connect(owner).addRewardDistributor(appId, owner.address); (0, chai_1.expect)(await x2EarnApps.isRewardDistributor(appId, owner.address)).to.equal(true); // distribute reward const tx = await x2EarnRewardsPool .connect(owner) .distributeRewardWithProofAndMetadata(appId, hardhat_1.ethers.parseEther("1"), user.address, ["image"], ["https://image.png"], ["carbon", "water"], [100, 200], "The description of the action", '{"country":"Brazil"}'); const receipt = await tx.wait(); (0, chai_1.expect)(await b3tr.balanceOf(user.address)).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPool.getAddress())).to.equal(hardhat_1.ethers.parseEther("99")); // event emitted if (!receipt) throw new Error("No receipt"); let event = (0, helpers_1.filterEventsByName)(receipt.logs, "RewardDistributed"); (0, chai_1.expect)(event).not.to.eql([]); (0, chai_1.expect)(event[0].args[0]).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(event[0].args[1]).to.equal(appId); (0, chai_1.expect)(event[0].args[2]).to.equal(user.address); const emittedProof = JSON.parse(event[0].args[3]); (0, chai_1.expect)(emittedProof).to.have.property("version"); (0, chai_1.expect)(emittedProof.version).to.equal(2); (0, chai_1.expect)(emittedProof).to.have.deep.property("proof", { image: "https://image.png" }); (0, chai_1.expect)(emittedProof).to.have.property("description"); (0, chai_1.expect)(emittedProof.description).to.equal("The description of the action"); (0, chai_1.expect)(emittedProof).to.have.deep.property("impact", { carbon: 100, water: 200 }); let eventMetadata = (0, helpers_1.filterEventsByName)(receipt.logs, "RewardMetadata"); (0, chai_1.expect)(eventMetadata).not.to.eql([]); (0, chai_1.expect)(eventMetadata[0].args[0]).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(eventMetadata[0].args[1]).to.equal(appId); (0, chai_1.expect)(eventMetadata[0].args[2]).to.equal(user.address); const emittedMetadata = JSON.parse(eventMetadata[0].args[3]); (0, chai_1.expect)(emittedMetadata).to.have.deep.property("country", "Brazil"); (0, chai_1.expect)(event[0].args[4]).to.equal(owner.address); }); (0, mocha_1.it)("Should not be able to upgrade if initial impact keys is empty", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, x2EarnApps, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, await b3tr.getAddress(), await x2EarnApps.getAddress(), ])); (0, chai_1.expect)(await x2EarnRewardsPoolV1.version()).to.equal("1"); // update x2EarnApps address await x2EarnRewardsPoolV1.connect(owner).setX2EarnApps(await x2EarnApps.getAddress()); // deposit some funds const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await x2EarnApps.connect(creator2).submitApp(owner.address, owner.address, "My app #2", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app"), owner); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app #2"), minterAccount); await b3tr.connect(owner).approve(await x2EarnRewardsPoolV1.getAddress(), amount); await x2EarnRewardsPoolV1.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPoolV1.getAddress())).to.equal(amount); // upgrade to new version await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, []], { version: 2, })).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, ["impact"]], { version: 2, })).to.not.be.reverted; }); (0, mocha_1.it)("Should not be able to upgrade to V3 if veBetterPassport address is empty", async () => { const config = (0, local_1.createLocalConfig)(); const { owner, b3tr, x2EarnApps, minterAccount, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, config, }); const x2EarnRewardsPoolV1 = (await (0, helpers_2.deployProxy)("X2EarnRewardsPoolV1", [ owner.address, owner.address, owner.address, await b3tr.getAddress(), await x2EarnApps.getAddress(), ])); (0, chai_1.expect)(await x2EarnRewardsPoolV1.version()).to.equal("1"); // update x2EarnApps address await x2EarnRewardsPoolV1.connect(owner).setX2EarnApps(await x2EarnApps.getAddress()); // deposit some funds const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await x2EarnApps.connect(creator2).submitApp(owner.address, owner.address, "My app #2", "metadataURI"); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app"), owner); await (0, xnodes_1.endorseApp)(await x2EarnApps.hashAppName("My app #2"), otherAccount); await b3tr.connect(owner).approve(await x2EarnRewardsPoolV1.getAddress(), amount); await x2EarnRewardsPoolV1.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPoolV1.getAddress())).to.equal(amount); // upgrade to new version await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV1", "X2EarnRewardsPoolV2", await x2EarnRewardsPoolV1.getAddress(), [owner.address, config.X_2_EARN_INITIAL_IMPACT_KEYS], { version: 2, })).to.not.be.reverted; await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV2", "X2EarnRewardsPool", await x2EarnRewardsPoolV1.getAddress(), [helpers_1.ZERO_ADDRESS], { version: 3, })).to.be.reverted; await (0, chai_1.expect)((0, helpers_2.upgradeProxy)("X2EarnRewardsPoolV2", "X2EarnRewardsPool", await x2EarnRewardsPoolV1.getAddress(), [owner.address], { version: 3, })).to.not.be.reverted; }); }); // settings (0, mocha_1.describe)("Settings", function () { (0, mocha_1.it)("CONTRACTS_ADDRESS_MANAGER_ROLE can set new x2EarnApps", async function () { const { x2EarnRewardsPool, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await x2EarnRewardsPool.hasRole(await x2EarnRewardsPool.CONTRACTS_ADDRESS_MANAGER_ROLE(), owner.address)).to.eql(true); await x2EarnRewardsPool.connect(owner).setX2EarnApps(await otherAccount.getAddress()); (0, chai_1.expect)(await x2EarnRewardsPool.x2EarnApps()).to.equal(await otherAccount.getAddress()); }); (0, mocha_1.it)("Only CONTRACTS_ADDRESS_MANAGER_ROLE can set new x2EarnApps", async function () { const { x2EarnRewardsPool, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); (0, chai_1.expect)(await x2EarnRewardsPool.hasRole(await x2EarnRewardsPool.CONTRACTS_ADDRESS_MANAGER_ROLE(), otherAccount.address)).to.eql(false); await (0, helpers_1.catchRevert)(x2EarnRewardsPool.connect(otherAccount).setX2EarnApps(await otherAccount.getAddress())); }); (0, mocha_1.it)("New x2EarnApps address cannot be the zero address", async function () { const { x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, helpers_1.catchRevert)(x2EarnRewardsPool.connect(owner).setX2EarnApps(helpers_1.ZERO_ADDRESS)); }); (0, mocha_1.it)("Can't send VET to the contract", async function () { const { x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, }); await (0, chai_1.expect)(owner.sendTransaction({ to: await x2EarnRewardsPool.getAddress(), value: hardhat_1.ethers.parseEther("1.0"), // Sends exactly 1.0 ether })).to.be.reverted; const balance = await hardhat_1.ethers.provider.getBalance(await x2EarnRewardsPool.getAddress()); (0, chai_1.expect)(balance).to.equal(0n); }); (0, mocha_1.it)("Can't send ERC721 to the contract", async function () { const { myErc721, x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, deployMocks: true, }); if (!myErc721) throw new Error("No ERC721 contract"); await myErc721.connect(owner).safeMint(owner.address, 1); // @ts-ignore await (0, chai_1.expect)(myErc721.connect(owner).safeTransferFrom(owner.address, await x2EarnRewardsPool.getAddress(), 1)).to .be.reverted; }); (0, mocha_1.it)("Cannot send ERC1155 to the contract", async function () { const { myErc1155, x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, deployMocks: true, }); if (!myErc1155) throw new Error("No ERC1155 contract"); await myErc1155.connect(owner).mint(owner.address, 1, 1, "0x"); // @ts-ignore await (0, chai_1.expect)(myErc1155.connect(owner).safeTransferFrom(owner.address, await x2EarnRewardsPool.getAddress(), 1, 1, "0x")).to.be.reverted; }); (0, mocha_1.it)("Cannot batch send ERC1155 to the contract", async function () { const { myErc1155, x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, deployMocks: true, }); if (!myErc1155) throw new Error("No ERC1155 contract"); await (0, chai_1.expect)(myErc1155.connect(owner).mintBatch(await x2EarnRewardsPool.getAddress(), [2, 3], [2, 3], new Uint8Array(0))).to.be.reverted; }); (0, mocha_1.it)("should revert when calling fallback function with call data", async function () { const { x2EarnRewardsPool, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: false, }); owner.sendTransaction({ to: await x2EarnRewardsPool.getAddress(), value: 0, data: "0x1234", // some data }); }); (0, mocha_1.it)("Can get and set veBetterPassport address", async function () { const { x2EarnRewardsPool, owner, otherAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true }); await x2EarnRewardsPool.connect(owner).setVeBetterPassport(owner.address); const updatedVeBetterPassportAddress = await x2EarnRewardsPool.veBetterPassport(); (0, chai_1.expect)(updatedVeBetterPassportAddress).to.eql(owner.address); // only admin can set the veBetterPassport address await (0, chai_1.expect)(x2EarnRewardsPool.connect(otherAccount).setVeBetterPassport(otherAccount.address)).to.be.reverted; }); }); // deposit (0, mocha_1.describe)("Deposit", function () { // everyone can deposit (0, mocha_1.it)("Anyone can deposit", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); // create app await x2EarnApps.connect(creator1).submitApp(owner.address, owner.address, "My app", "metadataURI"); await x2EarnApps.submitApp(owner.address, owner.address, "My app #2", "metadataURI"); const appId1 = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); const appId2 = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app #2")); await (0, xnodes_1.endorseApp)(appId1, owner); await (0, xnodes_1.endorseApp)(appId2, minterAccount); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), amount); await x2EarnRewardsPool.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPool.getAddress())).to.equal(amount); }); // app must exist (0, mocha_1.it)("Should not allow deposit to non-existing app", async function () { const { x2EarnRewardsPool, b3tr, owner, x2EarnApps } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), amount); await (0, helpers_1.catchRevert)(x2EarnRewardsPool.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app"))); }); // owner must approve token (0, mocha_1.it)("Should not allow deposit without approval", async function () { const { x2EarnRewardsPool, x2EarnApps, owner } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const amount = hardhat_1.ethers.parseEther("100"); await x2EarnApps.submitApp(owner.address, owner.address, "My app", "metadataURI"); const appId = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); await (0, xnodes_1.endorseApp)(appId, owner); await (0, helpers_1.catchRevert)(x2EarnRewardsPool.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app"))); }); (0, mocha_1.it)("Should emit Deposit event", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, otherAccount, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(otherAccount.address, amount); await x2EarnApps.submitApp(owner.address, owner.address, "My app", "metadataURI"); const appId = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); await (0, xnodes_1.endorseApp)(appId, owner); await b3tr.connect(otherAccount).approve(await x2EarnRewardsPool.getAddress(), amount); const tx = await x2EarnRewardsPool.connect(otherAccount).deposit(amount, await x2EarnApps.hashAppName("My app")); const receipt = await tx.wait(); if (!receipt) throw new Error("No receipt"); let event = (0, helpers_1.filterEventsByName)(receipt.logs, "NewDeposit"); (0, chai_1.expect)(event).not.to.eql([]); (0, chai_1.expect)(event[0].args[0]).to.equal(amount); (0, chai_1.expect)(event[0].args[1]).to.equal(await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(event[0].args[2]).to.equal(otherAccount.address); }); }); (0, mocha_1.describe)("Balance", function () { (0, mocha_1.it)("Should return correct balance", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); await x2EarnApps.submitApp(owner.address, owner.address, "My app", "metadataURI"); const appId = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); await (0, xnodes_1.endorseApp)(appId, owner); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), amount); await x2EarnRewardsPool.connect(owner).deposit(amount, await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(await x2EarnRewardsPool.availableFunds(await x2EarnApps.hashAppName("My app"))).to.equal(amount); }); }); // withdraw (0, mocha_1.describe)("Withdraw", function () { (0, mocha_1.it)("The admin of the app can withdraw", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, otherAccounts, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const teamWallet = otherAccounts[10]; const appAdmin = otherAccounts[11]; const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); await x2EarnApps.submitApp(teamWallet.address, appAdmin.address, "My app", "metadataURI"); const appId = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); await (0, xnodes_1.endorseApp)(appId, owner); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), amount); await x2EarnRewardsPool.connect(owner).deposit(amount, appId); (0, chai_1.expect)(await b3tr.balanceOf(teamWallet.address)).to.equal(0n); await x2EarnRewardsPool.connect(appAdmin).withdraw(hardhat_1.ethers.parseEther("1"), appId, ""); (0, chai_1.expect)(await b3tr.balanceOf(await x2EarnRewardsPool.getAddress())).to.equal(hardhat_1.ethers.parseEther("99")); // money are sent to team wallet (0, chai_1.expect)(await b3tr.balanceOf(teamWallet.address)).to.equal(hardhat_1.ethers.parseEther("1")); // can leave a reason const tx = await x2EarnRewardsPool .connect(appAdmin) .withdraw(hardhat_1.ethers.parseEther("1"), await x2EarnApps.hashAppName("My app"), "For the team"); // "Should emit Withdraw event" const receipt = await tx.wait(); if (!receipt) throw new Error("No receipt"); let event = (0, helpers_1.filterEventsByName)(receipt.logs, "TeamWithdrawal"); (0, chai_1.expect)(event).not.to.eql([]); (0, chai_1.expect)(event[0].args[0]).to.equal(hardhat_1.ethers.parseEther("1")); (0, chai_1.expect)(event[0].args[1]).to.equal(await x2EarnApps.hashAppName("My app")); (0, chai_1.expect)(event[0].args[2]).to.equal(teamWallet.address); (0, chai_1.expect)(event[0].args[3]).to.equal(appAdmin.address); (0, chai_1.expect)(event[0].args[4]).to.equal("For the team"); }); (0, mocha_1.it)("The app distributor cannot withdraw", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, otherAccounts, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const teamWallet = otherAccounts[10]; const appAdmin = otherAccounts[11]; const appDistributor = otherAccounts[12]; const amount = hardhat_1.ethers.parseEther("100"); await b3tr.connect(minterAccount).mint(owner.address, amount); await x2EarnApps.submitApp(teamWallet.address, appAdmin.address, "My app", "metadataURI"); const appId = hardhat_1.ethers.keccak256(hardhat_1.ethers.toUtf8Bytes("My app")); await (0, xnodes_1.endorseApp)(appId, owner); await x2EarnApps.connect(appAdmin).addRewardDistributor(appId, appDistributor.address); (0, chai_1.expect)(await x2EarnApps.isRewardDistributor(appId, appDistributor.address)).to.equal(true); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), amount); await x2EarnRewardsPool.connect(owner).deposit(amount, appId); (0, chai_1.expect)(await b3tr.balanceOf(teamWallet.address)).to.equal(0n); await (0, chai_1.expect)(x2EarnRewardsPool.connect(appDistributor).withdraw(hardhat_1.ethers.parseEther("1"), appId, "")).to.be.revertedWith("X2EarnRewardsPool: not an app admin"); }); (0, mocha_1.it)("App must exist", async function () { const { x2EarnRewardsPool, b3tr, owner, x2EarnApps } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); await b3tr.connect(owner).approve(await x2EarnRewardsPool.getAddress(), hardhat_1.ethers.parseEther("100")); await (0, helpers_1.catchRevert)(x2EarnRewardsPool.connect(owner).withdraw(hardhat_1.ethers.parseEther("1"), await x2EarnApps.hashAppName("My app"), "")); }); (0, mocha_1.it)("Normal users cannot withdraw", async function () { const { x2EarnRewardsPool, x2EarnApps, b3tr, owner, otherAccount, minterAccount } = await (0, helpers_1.getOrDeployContractInstances)({ forceDeploy: true, bootstrapAndStartEmissions: true, }); const teamWallet = otherAccount; const amount = hardhat_1.ethers.pars