import { expect } from 'chai' import hre from "hardhat"; import { ZeroAddress, getBytes, solidityPackedKeccak256, formatEther, JsonRpcProvider, } from 'ethers' import { loadFixture, } from "@nomicfoundation/hardhat-toolbox/network-helpers"; import { expandDecimals, increaseTime, mineBlock, reportGasUsed } from './shared/utilities'; const secondsOneDay = BigInt(24 * 60 * 60); const secondsPerYear = 365 * 24 * 60 * 60; // 1.5 / (365*24*60*60) const rewardPerSecond = BigInt(1.5 * 10 ** 18) / BigInt(secondsPerYear) ; // 47564688000 console.log('rewardPerSecond: ', rewardPerSecond.toString()) const blockTime = async (provider: any) => { const block = await provider.getBlock('latest') return block ? block.timestamp : 0 } const showLog = async (tag: string, stakedCecTracker: any, esCec: any, address: string) => { console.log(tag+'\t', 'stake amount:', formatEther(await stakedCecTracker.stakedAmounts(address)), 'claimable: ', formatEther(await stakedCecTracker.claimable(address)), 'claimableReward: ', formatEther(await stakedCecTracker.claimableReward(address)), 'esCec balance: ', formatEther(await esCec.balanceOf(address)), ) } describe('RewardRouter', function() { async function deployOneContract() { // Contracts are deployed using the first signer/account by default const [owner, user0, user1, user2] = await hre.ethers.getSigners(); const verifier = owner.address; const chainId = hre.network.config.chainId const Cec = await hre.ethers.getContractFactory("MintableBaseToken"); const cec = await Cec.deploy("test cec", "cec"); const EsToken = await hre.ethers.getContractFactory("EsToken"); const esCec = await EsToken.deploy("test esCec", "esCec"); const RewardTracker = await hre.ethers.getContractFactory("RewardTracker"); const RewardDistributor = await hre.ethers.getContractFactory("RewardDistributor"); const stakedCecTracker = await RewardTracker.deploy("Staked CEC", "sCEC"); const stakedCecDistributor = await RewardDistributor.deploy(esCec.target, stakedCecTracker.target); await stakedCecTracker.initialize([cec.target, esCec.target], stakedCecDistributor.target); await stakedCecDistributor.updateLastDistributionTime(); const Vester = await hre.ethers.getContractFactory("Vester"); const vester = await Vester.deploy( "Vested CEC", "veCEC", secondsPerYear, esCec.target, ZeroAddress, cec.target, ZeroAddress, false ); await stakedCecTracker.setInPrivateTransferMode(true) await stakedCecTracker.setInPrivateStakingMode(true) // await esCec.setInPrivateTransferMode(true) const RewardRouter = await hre.ethers.getContractFactory("RewardRouter"); const rewardRouter = await RewardRouter.deploy( cec.target, stakedCecTracker.target, vester.target, ); await esCec.setMinter(owner.address, true) await esCec.mint(stakedCecDistributor.target, expandDecimals(50000, 18)) await stakedCecDistributor.setTokensPerInterval(rewardPerSecond) await stakedCecTracker.setHandler(rewardRouter.target, true) await esCec.setMinter(vester.target, true) await esCec.setHandler(stakedCecTracker.target, true) return { owner, user0, user1, user2, chainId, cec, esCec, stakedCecTracker, stakedCecDistributor, vester, rewardRouter }; } describe("Deployment", function () { it('should deploy RewardRouter', async function() { const { chainId } = await loadFixture(deployOneContract); // expect((await nftClaimer.mintConfig()).mintPrice).to.equal(100); }); }) describe("Staking", function () { it("stakeCecForAccount, stakeCec, stakeEsCec, unstakeCec, unstakeEsCec, claimEsCec", async () => { const {owner, user0, user1, user2, chainId, cec, esCec, stakedCecTracker, stakedCecDistributor, vester, rewardRouter} = await loadFixture(deployOneContract); const wallet = owner const provider = wallet.provider; await cec.setMinter(wallet.address, true) await cec.mint(user0.address, expandDecimals(1500, 18)) expect(await cec.balanceOf(user0.address)).eq(expandDecimals(1500, 18)) // @ts-ignore await cec.connect(user0).approve(stakedCecTracker.target, expandDecimals(1000, 18)) // @ts-ignore await expect(rewardRouter.connect(user0).batchStakeCecForAccount([user1.address], [expandDecimals(1000, 18)])) .to.be.revertedWith("Governable: forbidden") await rewardRouter.setGov(user0.address) // @ts-ignore await rewardRouter.connect(user0).batchStakeCecForAccount([user1.address], [expandDecimals(800, 18)]) expect(await cec.balanceOf(user0.address)).eq(expandDecimals(700, 18)) await cec.mint(user1.address, expandDecimals(200, 18)) expect(await cec.balanceOf(user1.address)).eq(expandDecimals(200, 18)) // @ts-ignore await cec.connect(user1).approve(stakedCecTracker.target, expandDecimals(200, 18)) // @ts-ignore await rewardRouter.connect(user1).stakeCec(expandDecimals(200, 18)) expect(await cec.balanceOf(user1.address)).eq(0) expect(await stakedCecTracker.stakedAmounts(user0.address)).eq(0) expect(await stakedCecTracker.depositBalances(user0.address, cec.target)).eq(0) expect(await stakedCecTracker.stakedAmounts(user1.address)).eq(expandDecimals(1000, 18)) expect(await stakedCecTracker.depositBalances(user1.address, cec.target)).eq(expandDecimals(1000, 18)) const totalSupply = await stakedCecTracker.totalSupply() console.log('totalSupply: ', formatEther(totalSupply)) await showLog('init', stakedCecTracker, esCec, user1.address) await increaseTime(provider, Number(secondsOneDay)) await mineBlock(provider) await showLog('1day', stakedCecTracker, esCec, user1.address) expect(await stakedCecTracker.claimable(user0.address)).eq(0) expect(await stakedCecTracker.claimable(user1.address)).gt(expandDecimals(4, 18)) expect(await stakedCecTracker.claimable(user1.address)).lt(expandDecimals(5, 18)) // await timelock.signalMint(esCec.target, tokenManager.address, expandDecimals(500, 18)) await increaseTime(provider, 20) await mineBlock(provider) // await timelock.processMint(esCec.target, tokenManager.address, expandDecimals(500, 18)) // await esCec.connect(tokenManager).transferFrom(tokenManager.address, user2.address, expandDecimals(500, 18)) await cec.mint(user2.address, expandDecimals(500, 18)) // @ts-ignore await cec.connect(user2).approve(stakedCecTracker.target, expandDecimals(500, 18)) // @ts-ignore await rewardRouter.connect(user2).stakeCec(expandDecimals(500, 18)) expect(await stakedCecTracker.stakedAmounts(user0.address)).eq(0) expect(await stakedCecTracker.depositBalances(user0.address, cec.target)).eq(0) expect(await stakedCecTracker.stakedAmounts(user1.address)).eq(expandDecimals(1000, 18)) expect(await stakedCecTracker.depositBalances(user1.address, cec.target)).eq(expandDecimals(1000, 18)) expect(await stakedCecTracker.stakedAmounts(user2.address)).eq(expandDecimals(500, 18)) expect(await stakedCecTracker.depositBalances(user2.address, cec.target)).eq(expandDecimals(500, 18)) await increaseTime(provider, Number(secondsOneDay)) await mineBlock(provider) expect(await stakedCecTracker.claimable(user0.address)).eq(0) expect(await stakedCecTracker.claimable(user1.address)).gt(expandDecimals(8, 18)) expect(await stakedCecTracker.claimable(user1.address)).lt(expandDecimals(9, 18)) expect(await stakedCecTracker.claimable(user2.address)).gt(expandDecimals(2, 18)) expect(await stakedCecTracker.claimable(user2.address)).lt(expandDecimals(5, 18)) await showLog('2day', stakedCecTracker, esCec, user1.address) expect(await esCec.balanceOf(user1.address)).eq(0) // @ts-ignore await rewardRouter.connect(user1).claim() expect(await esCec.balanceOf(user1.address)).gt(expandDecimals(8, 18)) expect(await esCec.balanceOf(user1.address)).lt(expandDecimals(9, 18)) expect(await esCec.balanceOf(user2.address)).eq(0) // @ts-ignore await rewardRouter.connect(user2).claim() expect(await esCec.balanceOf(user2.address)).gt(expandDecimals(2, 18)) expect(await esCec.balanceOf(user2.address)).lt(expandDecimals(5, 18)) await increaseTime(provider, Number(secondsOneDay)) await mineBlock(provider) await increaseTime(provider, Number(secondsOneDay)) await mineBlock(provider) await showLog('claim cec 2day', stakedCecTracker, esCec, user1.address) // // @ts-ignore // await rewardRouter.connect(user1).stakeCec(await esCec.balanceOf(user1.address)) // await showLog('compound', stakedCecTracker, esCec, user1.address) // expect(await stakedCecTracker.stakedAmounts(user1.address)).gt(expandDecimals(1008, 18)) // expect(await stakedCecTracker.stakedAmounts(user1.address)).lt(expandDecimals(1009, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, cec.target)).eq(expandDecimals(1000, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, esCec.target)).gt(expandDecimals(8, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, esCec.target)).lt(expandDecimals(9, 18)) // expect(await cec.balanceOf(user1.address)).eq(0) // // @ts-ignore // await rewardRouter.connect(user1).unstakeCec(expandDecimals(300, 18)) // expect(await cec.balanceOf(user1.address)).eq(expandDecimals(300, 18)) // expect(await stakedCecTracker.stakedAmounts(user1.address)).gt(expandDecimals(708, 18)) // expect(await stakedCecTracker.stakedAmounts(user1.address)).lt(expandDecimals(709, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, cec.target)).eq(expandDecimals(700, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, esCec.target)).gt(expandDecimals(8, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, esCec.target)).lt(expandDecimals(9, 18)) // const esCecBalance1 = await esCec.balanceOf(user1.address) // const esCecUnstakeBalance1 = await stakedCecTracker.depositBalances(user1.address, esCec.target) // // @ts-ignore // await rewardRouter.connect(user1).unstakeCec(esCecUnstakeBalance1) // expect(await esCec.balanceOf(user1.address)).eq(esCecBalance1 + esCecUnstakeBalance1) // expect(await stakedCecTracker.stakedAmounts(user1.address)).eq(expandDecimals(700, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, cec.target)).eq(expandDecimals(700, 18)) // expect(await stakedCecTracker.depositBalances(user1.address, esCec.target)).eq(0) // // @ts-ignore // await expect(rewardRouter.connect(user1).unstakeCec(expandDecimals(1, 18))) // .to.be.revertedWith("RewardTracker: _amount exceeds depositBalance") }) }) })