@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
JavaScript
"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