contracts-imtbl/test/testVester.ts
2024-09-14 15:19:59 +08:00

297 lines
14 KiB
TypeScript

import {expect} from "chai";
import hre from "hardhat";
import {getBytes, solidityPackedKeccak256, ZeroAddress} from "ethers";
import {loadFixture} from "@nomicfoundation/hardhat-toolbox/network-helpers";
import {expandDecimals, getBlockTime, increaseTime, mineBlock} from "./shared/utilities";
const secondsPerYear = BigInt(365 * 24 * 60 * 60);
const rewardPerSecond = BigInt(1.5 * 10 ** 18) / secondsPerYear ;
describe("Vester", function () {
async function deployOneContract() {
// Contracts are deployed using the first signer/account by default
const [owner, otherAccount] = await hre.ethers.getSigners();
const verifier = owner.address;
const chainId = hre.network.config.chainId;
const Cec = await hre.ethers.getContractFactory("EsToken");
const cec = await Cec.deploy("test cec", "cec");
const esCec = await Cec.deploy("test esCec", "esCec");
await cec.setMinter(owner.address, true);
await esCec.setMinter(owner.address, true);
const RewardTracker = await hre.ethers.getContractFactory("RewardTracker");
const stakedCecTracker = await RewardTracker.deploy(esCec.target, cec.target, rewardPerSecond, 18);
const Vester = await hre.ethers.getContractFactory("Vester");
const vester = await Vester.deploy(
"Vested CEC",
"veCEC",
secondsPerYear,
esCec.target,
cec.target,
stakedCecTracker.target,
ZeroAddress,
true
);
await cec.mint(owner.address, expandDecimals(100000, 18));
await esCec.mint(owner.address, expandDecimals(100000, 18));
return {owner, otherAccount, chainId, cec, esCec, vester, stakedCecTracker};
}
describe("Deployment", function () {
it("should deploy Vester", async function () {
const {cec, esCec, vester, stakedCecTracker} = await loadFixture(deployOneContract);
expect(await vester.name()).eq("Vested CEC");
expect(await vester.symbol()).eq("veCEC");
expect(await vester.vestingDuration()).eq(secondsPerYear);
expect(await vester.esToken()).eq(esCec.target);
expect(await vester.claimableToken()).eq(cec.target);
expect(await vester.rewardTrackerCEC()).eq(stakedCecTracker.target);
expect(await vester.hasRewardTrackerCEC()).eq(true);
});
it("setCumulativeRewardDeductions", async () => {
const {owner, otherAccount, cec, esCec, vester} = await loadFixture(deployOneContract);
await expect(vester.setCumulativeRewardDeductions(owner.address, 200)).to.be.revertedWith("Vester: forbidden");
await vester.setHandler(owner.address, true);
expect(await vester.cumulativeRewardDeductions(owner.address)).eq(0);
await vester.setCumulativeRewardDeductions(owner.address, 200);
expect(await vester.cumulativeRewardDeductions(owner.address)).eq(200);
});
it("setBonusRewards", async () => {
const {owner, otherAccount, cec, esCec, vester} = await loadFixture(deployOneContract);
await expect(vester.setBonusRewards(owner.address, 200)).to.be.revertedWith("Vester: forbidden");
await vester.setHandler(owner.address, true);
expect(await vester.bonusRewards(owner.address)).eq(0);
await vester.setBonusRewards(owner.address, 200);
expect(await vester.bonusRewards(owner.address)).eq(200);
});
it("deposit, claim, withdraw", async () => {
const {owner, otherAccount, cec, esCec, vester, stakedCecTracker} = await loadFixture(deployOneContract);
const wallet = owner;
const user0 = otherAccount;
const provider = wallet.provider;
await vester.setHandler(wallet.address, true);
await esCec.setMinter(vester.target, true);
// @ts-ignore
await expect(vester.connect(user0).deposit(0)).to.be.revertedWith("Vester: invalid _amount");
// @ts-ignore
await expect(vester.connect(user0).deposit(expandDecimals(1000, 18))).to.be.revertedWith(
"ERC20: insufficient allowance",
);
await esCec.setHandler(vester.target, true);
await esCec.setInPrivateTransferMode(true);
await esCec.setHandler(wallet.address, true);
// @ts-ignore
// await esCec.connect(user0).approve(vester.target, expandDecimals(1000, 18));
// @ts-ignore
await expect(vester.connect(user0).deposit(expandDecimals(1000, 18))).to.be.revertedWith(
"ERC20: transfer amount exceeds balance",
);
expect(await vester.balanceOf(user0.address)).eq(0);
expect(await vester.getTotalVested(user0.address)).eq(0);
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(0);
expect(await vester.claimedAmounts(user0.address)).eq(0);
expect(await vester.claimable(user0.address)).eq(0);
expect(await vester.lastVestingTimes(user0.address)).eq(0);
await esCec.mint(user0.address, expandDecimals(1000, 18));
await vester.setBonusRewards(user0.address, expandDecimals(10_000, 18));
// @ts-ignore
await expect(vester.connect(user0).deposit(expandDecimals(1000, 18))).to.be.revertedWith(
"Vester: insufficient cec balance",
);
await stakedCecTracker.setHandler(user0.address, true);
await cec.setMinter(wallet.address, true);
await cec.mint(user0.address, expandDecimals(1000, 18));
// @ts-ignore
await cec.connect(user0).approve(stakedCecTracker.target, expandDecimals(1000, 18));
// @ts-ignore
await stakedCecTracker.connect(user0).stakeForAccount(user0.address, user0.address, cec.target, expandDecimals(1000, 18));
// @ts-ignore
await vester.connect(user0).deposit(expandDecimals(1000, 18));
let blockTime = await getBlockTime(provider);
expect(await vester.balanceOf(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.getTotalVested(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(0);
expect(await vester.claimedAmounts(user0.address)).eq(0);
expect(await vester.claimable(user0.address)).eq(0);
expect(await vester.lastVestingTimes(user0.address)).eq(blockTime);
await increaseTime(provider, 24 * 60 * 60);
await mineBlock(provider);
expect(await esCec.balanceOf(user0.address)).eq(0);
expect(await cec.balanceOf(user0.address)).eq(0);
expect(await vester.balanceOf(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.getTotalVested(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(0);
expect(await vester.claimedAmounts(user0.address)).eq(0);
let lastDepositTime = await vester.lastDepositTimes(user0.address);
let lastVestingTime = BigInt(await vester.lastVestingTimes(user0.address));
expect(lastDepositTime).eq(lastVestingTime);
let now = await getBlockTime(provider);
let total = BigInt(1000) * BigInt(10 ** 18) * (BigInt(now) - lastDepositTime) / BigInt(secondsPerYear);
expect(await vester.claimable(user0.address)).eq(total);
expect(await vester.lastVestingTimes(user0.address)).eq(blockTime);
// @ts-ignore
await expect(vester.connect(user0).claim()).to.be.revertedWith("ERC20: transfer amount exceeds balance");
await cec.mint(vester.target, expandDecimals(2000, 18));
// @ts-ignore
await vester.connect(user0).claim();
blockTime = await getBlockTime(provider);
lastDepositTime = await vester.lastDepositTimes(user0.address);
now = await getBlockTime(provider);
total = BigInt(1000) * (now - lastDepositTime) * BigInt(10 ** 18) / BigInt(secondsPerYear);
expect(await esCec.balanceOf(user0.address)).eq(0);
expect(await cec.balanceOf(user0.address)).eq(total);
let cecAmount = await cec.balanceOf(user0.address);
let claimed = cecAmount;
expect(await vester.balanceOf(user0.address)).eq(expandDecimals(1000, 18) - cecAmount);
expect(cecAmount).eq(total);
expect(await vester.getTotalVested(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimedAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimable(user0.address)).eq(0);
expect(await vester.lastVestingTimes(user0.address)).eq(blockTime);
await increaseTime(provider, 48 * 60 * 60);
await mineBlock(provider);
lastDepositTime = await vester.lastDepositTimes(user0.address);
let pre = now
now = await getBlockTime(provider);
let _claimable = BigInt(1000) * (now - pre) * BigInt(10 ** 18) / BigInt(secondsPerYear);
lastVestingTime = BigInt(await vester.lastVestingTimes(user0.address));
expect(pre).eq(lastVestingTime);
expect(await vester.claimedAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimable(user0.address)).eq(total - claimed + _claimable);
await increaseTime(provider, parseInt(365 / 2 - 1 + "") * 24 * 60 * 60);
await mineBlock(provider);
let tmpNow = await getBlockTime(provider);
_claimable = BigInt(1000) * (tmpNow - pre) * BigInt(10 ** 18) / BigInt(secondsPerYear);
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimedAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimable(user0.address)).eq(total - cecAmount + _claimable);
// @ts-ignore
await vester.connect(user0).claim();
blockTime = await getBlockTime(provider);
now = await getBlockTime(provider);
_claimable = BigInt(1000) * (now - pre) * BigInt(10 ** 18) / BigInt(secondsPerYear);
total += _claimable;
pre = now;
cecAmount += (total - cecAmount)
expect(await esCec.balanceOf(user0.address)).eq(0);
expect(await cec.balanceOf(user0.address)).eq(cecAmount);
cecAmount = await cec.balanceOf(user0.address);
expect(await vester.balanceOf(user0.address)).eq(expandDecimals(1000, 18) - cecAmount);
expect(await vester.getTotalVested(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimedAmounts(user0.address)).eq(cecAmount);
expect(await vester.claimable(user0.address)).eq(0);
expect(await vester.lastVestingTimes(user0.address)).eq(blockTime);
await increaseTime(provider, 24 * 60 * 60);
await mineBlock(provider);
// vesting rate should be the same even after claiming
tmpNow = await getBlockTime(provider);
_claimable = BigInt(1000) * (tmpNow - pre) * BigInt(10 ** 18) / BigInt(secondsPerYear);
expect(await vester.claimable(user0.address)).eq(total - cecAmount + _claimable); // 1000 / 365 => ~2.739
await esCec.mint(user0.address, expandDecimals(500, 18));
// @ts-ignore
// await esCec.connect(user0).approve(vester.target, expandDecimals(500, 18));
// @ts-ignore
await vester.connect(user0).deposit(expandDecimals(500, 18));
tmpNow = await getBlockTime(provider);
_claimable = BigInt(1000) * (tmpNow - pre) * BigInt(10 ** 18) / BigInt(secondsPerYear);
let _balance1 = await vester.balanceOf(user0.address);
let _balance2 = (BigInt(1000) * BigInt(10 ** 18) - cecAmount) + BigInt(500) * BigInt(10 ** 18) - _claimable
expect(_balance1).eq(_balance2);
let vestTotal = await vester.vestingTotal(user0.address);
expect(vestTotal).eq(_balance2);
total += _claimable;
pre = tmpNow;
lastVestingTime = BigInt(await vester.lastVestingTimes(user0.address));
expect(pre).eq(lastVestingTime);
await increaseTime(provider, 24 * 60 * 60);
await mineBlock(provider);
tmpNow = await getBlockTime(provider);
_claimable = BigInt(_balance2) * (tmpNow - pre) / BigInt(secondsPerYear);
expect(await esCec.balanceOf(user0.address)).eq(0);
expect(await cec.balanceOf(user0.address)).eq(cecAmount);
expect(await vester.claimable(user0.address)).eq(total - cecAmount + _claimable);
// @ts-ignore
await vester.connect(user0).withdraw();
tmpNow = await getBlockTime(provider);
_claimable = BigInt(_balance2) * (tmpNow - pre) / BigInt(secondsPerYear);
cecAmount += (total - cecAmount + _claimable);
expect(await cec.balanceOf(user0.address)).eq(cecAmount);
expect(await vester.balanceOf(user0.address)).eq(0);
expect(await vester.getTotalVested(user0.address)).eq(0);
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(0);
expect(await vester.claimedAmounts(user0.address)).eq(0);
expect(await vester.claimable(user0.address)).eq(0);
expect(await vester.lastVestingTimes(user0.address)).eq(0);
// @ts-ignore
// await esCec.connect(user0).approve(vester.target, expandDecimals(1000, 18));
await esCec.mint(user0.address, expandDecimals(1000, 18));
// @ts-ignore
await vester.connect(user0).deposit(expandDecimals(1000, 18));
blockTime = await getBlockTime(provider);
await increaseTime(provider, 24 * 60 * 60);
await mineBlock(provider);
expect(await vester.balanceOf(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.getTotalVested(user0.address)).eq(expandDecimals(1000, 18));
expect(await vester.cumulativeClaimAmounts(user0.address)).eq(0);
expect(await vester.claimedAmounts(user0.address)).eq(0);
expect(await vester.claimable(user0.address)).gt("2730000000000000000"); // 1000 / 365 => ~2.739
expect(await vester.claimable(user0.address)).lt("2750000000000000000");
expect(await vester.lastVestingTimes(user0.address)).eq(blockTime);
// @ts-ignore
await vester.connect(user0).claim();
});
});
});