From 663ae5c954bb9df71e9070d3887824a7c55bbc8f Mon Sep 17 00:00:00 2001 From: weiqiushi Date: Tue, 14 May 2024 21:16:31 +0800 Subject: [PATCH] Dividend contract use block timestamp instead of block number. Upload dmc2.0 deploy script. Adjust exchange and bridge param --- contracts/dividend.sol | 18 +- contracts/dmc_bridge.sol | 4 +- contracts/exchange.sol | 2 +- scripts/deploy_dmc2.ts | 49 ++ test/test_dividend2.ts | 1272 +++++++++++++++++++------------------- 5 files changed, 696 insertions(+), 649 deletions(-) create mode 100644 scripts/deploy_dmc2.ts diff --git a/contracts/dividend.sol b/contracts/dividend.sol index f753450..489456d 100644 --- a/contracts/dividend.sol +++ b/contracts/dividend.sol @@ -19,9 +19,6 @@ contract DividendContract is Initializable, UUPSUpgradeable, ReentrancyGuardUpgr // current cycle index, start at 0 uint256 public currentCycleIndex; - // the start block of the cycle of the contract - uint256 public cycleStartBlock; - struct RewardInfo { address token; uint256 amount; @@ -35,7 +32,7 @@ contract DividendContract is Initializable, UUPSUpgradeable, ReentrancyGuardUpgr struct CycleInfo { // The start block of the cycle - uint256 startBlock; + uint256 startBlocktime; // the total stake amount of the curent cycle uint256 totalStaked; @@ -87,12 +84,13 @@ contract DividendContract is Initializable, UUPSUpgradeable, ReentrancyGuardUpgr function __DividendContractUpgradable_init(address _stakingToken, uint256 _cycleMaxLength, address[] memory _tokenList) public onlyInitializing { stakingToken = _stakingToken; cycleMaxLength = _cycleMaxLength; - cycleStartBlock = block.number; for (uint i = 0; i < _tokenList.length; i++) { tokenWhiteList[_tokenList[i]] = true; tokenWhiteListArray.push(_tokenList[i]); } + + cycles[0].startBlocktime = block.timestamp; } function getCurrentCycleIndex() public view returns (uint256) { @@ -333,21 +331,21 @@ contract DividendContract is Initializable, UUPSUpgradeable, ReentrancyGuardUpgr // check point for the new cycle function tryNewCycle() public { - uint256 currentBlock = block.number; + uint256 currentBlocktime = block.timestamp; CycleInfo storage currentCycle = cycles[currentCycleIndex]; - if (currentBlock - currentCycle.startBlock >= cycleMaxLength) { + if (currentBlocktime - currentCycle.startBlocktime >= cycleMaxLength) { currentCycleIndex = currentCycleIndex + 1; - // console.log("enter new cycle %d, totalStaked %d", currentCycleIndex, totalStaked); + console.log("enter new cycle %d, totalStaked %d", currentCycleIndex, totalStaked); CycleInfo storage newCycle = cycles[currentCycleIndex]; - newCycle.startBlock = currentBlock; + newCycle.startBlocktime = currentBlocktime; newCycle.totalStaked = totalStaked; if (currentCycle.totalStaked == 0) { newCycle.rewards = currentCycle.rewards; } - emit NewCycle(currentCycleIndex, currentBlock); + emit NewCycle(currentCycleIndex, currentBlocktime); } } diff --git a/contracts/dmc_bridge.sol b/contracts/dmc_bridge.sol index 9c13244..f40e4bc 100644 --- a/contracts/dmc_bridge.sol +++ b/contracts/dmc_bridge.sol @@ -15,7 +15,7 @@ contract DMCBridge is Ownable { } function getClaimableDMC2(string calldata cookie) public view returns (uint256) { - return dmc1_to_dmc2[keccak256(abi.encodePacked(msg.sender, cookie))] * 79 / 100; + return dmc1_to_dmc2[keccak256(abi.encodePacked(msg.sender, cookie))]; } function registerDMC1(address[] calldata recvAddress, string[] calldata cookie, uint256[] calldata dmc1Amount) onlyOwner public { @@ -28,7 +28,7 @@ contract DMCBridge is Ownable { function claimDMC2(string calldata cookie) public { bytes32 key = keccak256(abi.encodePacked(msg.sender, cookie)); require(dmc1_to_dmc2[key] > 0, "no dmc1 amount"); - uint256 dmc2Amount = dmc1_to_dmc2[key] * 79 / 100; + uint256 dmc2Amount = dmc1_to_dmc2[key]; dmc1_to_dmc2[key] = 0; dmc2.transfer(msg.sender, dmc2Amount); diff --git a/contracts/exchange.sol b/contracts/exchange.sol index 02220da..3ae5246 100644 --- a/contracts/exchange.sol +++ b/contracts/exchange.sol @@ -73,7 +73,7 @@ contract Exchange is Initializable, UUPSUpgradeable, OwnableUpgradeable { dmc2gwt_rate = 210; adjust_period = 21; - initial_dmc_balance = 768242.27 ether; + initial_dmc_balance = 972459 ether; test_mode = true; diff --git a/scripts/deploy_dmc2.ts b/scripts/deploy_dmc2.ts new file mode 100644 index 0000000..7f8ccb7 --- /dev/null +++ b/scripts/deploy_dmc2.ts @@ -0,0 +1,49 @@ +import { ethers, upgrades } from "hardhat"; +import { DividendContract, Exchange } from "../typechain-types"; + +async function main() { + let signers = await ethers.getSigners(); + let dmc = await (await ethers.deployContract("DMC", [ + ethers.parseEther("1000000000"), // 总量10亿 + ["0x000000000EefEA4e8A67d7434a02054b955Da62c", "0xDDDDDdDd91f172a0ceA030d20f68348E0370fE66", "0xCcCCCCCC5b74A876dB192d55ef8e4A60EfA1Eb5C", "0xad82A5fb394a525835A3a6DC34C1843e19160CFA"], + [ethers.parseEther("450000000"), ethers.parseEther("4500000"), ethers.parseEther("45000000"), ethers.parseEther("500000")]])).waitForDeployment() + + let dmcAddress = await dmc.getAddress(); + console.log("DMC address:", dmcAddress); + + let gwt = await (await ethers.deployContract("GWT", [[], []])).waitForDeployment(); + let gwtAddress = await gwt.getAddress(); + console.log("GWT address:", gwtAddress); + + let dividend = (await ( + await upgrades.deployProxy( + await ethers.getContractFactory("DividendContract"), + [dmcAddress, 7 * 24 * 60 * 60, [gwtAddress, ethers.ZeroAddress]], + { + initializer: "initialize", + kind: "uups", + timeout: 0 + } + ) + ).waitForDeployment()) as unknown as DividendContract; + + let dividendAddress = await dividend.getAddress(); + console.log("Dividend address:", dividendAddress); + + let exchange = await (await upgrades.deployProxy(await ethers.getContractFactory("Exchange"), + [await dmc.getAddress(), await gwt.getAddress(), dividendAddress, 7 * 24 * 60 * 60], + { + initializer: "initialize", + kind: "uups", + timeout: 0 + })).waitForDeployment() as unknown as Exchange; + let exchangeAddr = await exchange.getAddress(); + console.log("exchange address:", exchangeAddr); + + console.log("enable mint"); + + await (await dmc.enableMinter([exchangeAddr])).wait(); + await (await gwt.enableMinter([exchangeAddr])).wait(); +} + +main().then(() => process.exit(0)); \ No newline at end of file diff --git a/test/test_dividend2.ts b/test/test_dividend2.ts index 3ff192f..7f66a8f 100644 --- a/test/test_dividend2.ts +++ b/test/test_dividend2.ts @@ -1,645 +1,645 @@ import { ethers, upgrades } from "hardhat"; -import { DMC2, GWTToken2, DividendContract } from "../typechain-types"; +import { DMC, GWT, DividendContract } from "../typechain-types"; import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import { assert, expect } from "chai"; import { mine } from "@nomicfoundation/hardhat-network-helpers"; describe("Devidend", function () { - let dmc: DMC2; - let gwt: GWTToken2; - //let dividend: Dividend2; - let dividend: DividendContract; - let signers: HardhatEthersSigner[]; - - before(async () => { - signers = await ethers.getSigners(); - - dmc = await ( - await ethers.deployContract("DMC2", [ - ethers.parseEther("1000000000"), - [signers[0].address], - [1000000], - ]) - ).waitForDeployment(); - gwt = await (await ethers.deployContract("GWTToken2")).waitForDeployment(); - //dividend = await (await ethers.deployContract("Dividend2", [await dmc.getAddress(), 1000])).waitForDeployment() - - // add init token address as white list, address(0) and gwt token address - const tokenWhiteList = [ - await gwt.getAddress(), - "0x0000000000000000000000000000000000000000", - ]; - - dividend = (await ( - await upgrades.deployProxy( - await ethers.getContractFactory("DividendContract"), - [await dmc.getAddress(), 1000, tokenWhiteList] - ) - ).waitForDeployment()) as unknown as DividendContract; - - // 给signers[0] 1000个GWT - await (await gwt.enableMinter([signers[0].address])).wait(); - await (await gwt.mint(signers[0].address, 10000)).wait(); - await (await gwt.approve(await dividend.getAddress(), 10000)).wait(); - - // 给signers[1]到19, 每人100个DMC - for (let i = 1; i < 3; i++) { - await (await dmc.transfer(signers[i].address, 100)).wait(); - await ( - await dmc.connect(signers[i]).approve(await dividend.getAddress(), 1000) - ).wait(); - } - - // 测试白名单 - await (await dividend.addTokenToWhitelist(await gwt.getAddress())).wait(); - }); - - it("test init", async () => { - // test white list, only owner can add token to white list - dividend.connect(signers[0]).addTokenToWhitelist(await gwt.getAddress()); - - // test not owner - await expect( - dividend.connect(signers[1]).addTokenToWhitelist(await gwt.getAddress()) - ).to.be.reverted; - - // test remove token from white list - await ( - await dividend.removeTokenFromWhitelist(await gwt.getAddress()) - ).wait(); - - // test is in white list - expect( - await dividend.isTokenInWhitelisted(await gwt.getAddress()) - ).to.equal(false); - - // add again - await (await dividend.addTokenToWhitelist(await gwt.getAddress())).wait(); - expect( - await dividend.isTokenInWhitelisted(await gwt.getAddress()) - ).to.equal(true); - - // display the white list - const whiteList = await dividend.getTokenWhitelist(); - console.log("white list: ", whiteList); - }); - - it("test cycle 0", async () => { - // 初始周期0 - expect(await dividend.getCurrentCycleIndex()).to.equal(0); - await dividend.tryNewCycle(); - expect(await dividend.getCurrentCycleIndex()).to.equal(0); - - // error unstake and withdraw test - await expect(dividend.connect(signers[1]).unstake(50)).to.be.revertedWith( - "No stake record found" - ); - await expect( - dividend - .connect(signers[1]) - .withdrawDividends([0], [await gwt.getAddress()]) - ).to.be.revertedWith("Cannot claim current or future cycle"); - - await expect(dividend.connect(signers[0]).unstake(50)).to.be.revertedWith( - "No stake record found" - ); - await expect( - dividend - .connect(signers[0]) - .withdrawDividends([0, 1, 2], [await gwt.getAddress()]) - ).to.be.revertedWith("Cannot claim current or future cycle"); - - // test getStakeAmount with signer[0] - expect(await dividend.connect(signers[0]).getStakeAmount(0)).to.equal(0); - await expect( - dividend.connect(signers[0]).getStakeAmount(1) - ).to.be.revertedWith("Invalid cycle index"); - - await expect( - dividend.connect(signers[1]).getStakeAmount(10) - ).to.be.revertedWith("Invalid cycle index"); - }); - - it("test cycle 1", async () => { - mine(1000); - expect(await dividend.getCurrentCycleIndex()).to.equal(0); - - { - // check the token balance is 0 - await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - 0 - ); - - // 打入100 GWT, 前进到周期1 - await (await dividend.deposit(90, await gwt.getAddress())).wait(); - - await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - 90 - ); - - // direct transfer to dividend contract - await (await gwt.transfer(await dividend.getAddress(), 10)).wait(); - await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - 100 - ); - } - - expect(await dividend.getCurrentCycleIndex()).to.equal(1); - - // check stake amount with signer[1] - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(0); - await expect( - dividend.connect(signers[1]).getStakeAmount(2) - ).to.be.revertedWith("Invalid cycle index"); - - // 第1周期,signers1,2分别stake 50 DMC - await (await dividend.connect(signers[1]).stake(50)).wait(); - await (await dividend.connect(signers[2]).stake(50)).wait(); - - // check dmc balance for signer[1] and signer[2] - expect(await dmc.balanceOf(signers[1].address)).to.equal(50); - expect(await dmc.balanceOf(signers[2].address)).to.equal(50); - - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[2]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); - await expect( - dividend.connect(signers[2]).getStakeAmount(2) - ).to.be.revertedWith("Invalid cycle index"); - - // test withdraw dividends with cycle 0 - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([0], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[1].address)).to.equal(0); - - // test withdraw dividends with cycle 1 with revert - await expect( - dividend - .connect(signers[1]) - .withdrawDividends([1], [await gwt.getAddress()]) - ).to.be.revertedWith("Cannot claim current or future cycle"); - - await expect( - dividend - .connect(signers[1]) - .withdrawDividends([2], [await gwt.getAddress()]) - ).to.be.revertedWith("Cannot claim current or future cycle"); - - // test withdraw dividends with unknown tokens - // nothing to withdraw - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([0], [await signers[1].address]) - ).wait(); - }); - - it("test cycle 2", async () => { - // 又打入100 GWT,前进到周期2, 此时总分红200 GWT,因为周期1没有完整的抵押,所以周期1的分红是提不到的 - mine(1000); - await (await dividend.deposit(100, await gwt.getAddress())).wait(); - - // check stake amount with signer[1] and signer[2] - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(50); - - expect(await dividend.connect(signers[2]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); - - // 因为周期1开始时没有已确定的抵押,周期1的分红是提不到的 - const balance = await gwt.balanceOf(signers[1].address); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([1], [await gwt.getAddress()]) - ).wait(); - - const afterBalance = await gwt.balanceOf(signers[1].address); - expect(balance).to.equal(afterBalance); - - // withdraw with error cycle - await expect( - dividend - .connect(signers[1]) - .withdrawDividends([2], [await gwt.getAddress()]) - ).to.be.revertedWith("Cannot claim current or future cycle"); - - // withdraw with no stake - await ( - await dividend - .connect(signers[3]) - .withdrawDividends([1, 0], [await gwt.getAddress()]) - ).wait(); - const balance2 = await gwt.balanceOf(signers[3].address); - expect(balance2).to.equal(0); - - // stake and unstake only on current cycle - { - await (await dividend.connect(signers[1]).stake(20)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(30); - - // check stake amount with signer[1] - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); - - await (await dividend.connect(signers[1]).unstake(15)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(45); - - // check stake amount with signer[1] - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(55); - - await (await dividend.connect(signers[1]).unstake(5)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(50); - - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(50); - } - - { - // test error stake - await expect(dividend.connect(signers[1]).stake(0)).to.be.revertedWith( - "Cannot stake 0" - ); - } - - { - // test error unstake - await expect( - dividend.connect(signers[1]).unstake(100) - ).to.be.revertedWith("Insufficient stake amount"); - - await expect(dividend.connect(signers[1]).unstake(0)).to.be.revertedWith( - "Cannot unstake 0" - ); - } - - { - // test stake and unstake with effect prev cycle - await (await dividend.connect(signers[1]).stake(20)).wait(); - await (await dividend.connect(signers[1]).stake(10)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(20); - - await (await dividend.connect(signers[1]).unstake(45)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(65); - - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(35); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(35); - - await (await dividend.connect(signers[1]).stake(35)).wait(); - expect(await dmc.balanceOf(signers[1].address)).to.equal(30); - expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); - expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(35); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); - } - }); - - it("test cycle 3", async () => { - // 前进到周期3,周期2的分红200 GWT,周期3的分红100 GWT - mine(1500); - await (await dividend.deposit(100, await gwt.getAddress())).wait(); - - // check cycle is 3 now - expect(await dividend.getCurrentCycleIndex()).to.equal(3); - - // cycle 2, total stake 50 + 35 = 85, singer1 stake 35, should get 200 * 35 / 85 = 82 - // and signer2 stake 50, should get 200 * 50 / 85 = 117.6 - - // check full stake amount for signer[1] and signer[2] in cycle 2 - expect(await dividend.connect(signers[1]).getStakeAmount(2 - 1)).to.equal( - 35 - ); - expect(await dividend.connect(signers[2]).getStakeAmount(2 - 1)).to.equal( - 50 - ); - - // record the token balance of the contract - let balance_prev; - { - balance_prev = BigInt( - await dividend.getDepositTokenBalance(gwt.getAddress()) - ); - console.log("balance_prev: ", balance_prev); - - // try update once - await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - balance_prev - ); - } - - // test withdraw dividends with cycle 2 for signer[1] - expect( - await dividend - .connect(signers[1]) - .isDividendWithdrawed(2, await gwt.getAddress()) - ).to.equal(false); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([2], [await gwt.getAddress()]) - ).wait(); - expect( - await dividend - .connect(signers[1]) - .isDividendWithdrawed(2, await gwt.getAddress()) - ).to.equal(true); - expect(await gwt.balanceOf(signers[1].address)).to.equal(82); - - // verify the token balance of the contract after withdraw - { - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - balance_prev - 82n - ); - await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - balance_prev - 82n - ); - } - - // test withdraw second time with cycle 2 for signer[1], will be reverted - await expect( - dividend - .connect(signers[1]) - .withdrawDividends([2], [await gwt.getAddress()]) - ).to.be.revertedWith("Already claimed"); - - await expect( - dividend - .connect(signers[1]) - .withdrawDividends( - [2], - [await gwt.getAddress(), "0x0000000000000000000000000000000000000000"] - ) - ).to.be.revertedWith("Already claimed"); - - // 周期3,signer1先存20, 再提取45 DMC出来, 所以周期3的质押实际上是减少了25, 70-25=45 - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); - - // print total balance of stake token in contract - const balance = await dmc.balanceOf(await dividend.getAddress()); - console.log("total stake amount of DMC in contract: ", balance); - - // check balance with getTotalStaked with current cycle - expect( - await dividend.getTotalStaked(await dividend.getCurrentCycleIndex()) - ).to.equal(balance); - expect(balance).to.equal(120); - - await (await dividend.connect(signers[1]).stake(20)).wait(); - - const balance2 = await dmc.balanceOf(await dividend.getAddress()); - console.log( - "total stake amount of DMC in contract after stake: ", - balance2 - ); - expect( - await dividend.getTotalStaked(await dividend.getCurrentCycleIndex()) - ).to.equal(balance2); - expect(balance2).to.equal(140); - - await (await dividend.connect(signers[1]).unstake(45)).wait(); - expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(45); - - // test withdraw dividends with cycle 2 for signer[2], witch stake amount is 50 and should get 117 - expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); - await (await dividend.connect(signers[2]).stake(10)).wait(); - await (await dividend.connect(signers[2]).unstake(9)).wait(); - await (await dividend.connect(signers[2]).unstake(1)).wait(); - expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); - expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); - - /* - await dividend - .connect(signers[2]) - .withdrawDividends([2], [await gwt.getAddress()]); - expect(await gwt.balanceOf(signers[2].address)).to.equal(117); - */ - }); - - it("test cycle 4", async () => { - // 强制结算周期3,进入周期4 - mine(1000); - await (await dividend.tryNewCycle()).wait(); - - // check gwt balance of the contract - // 300 - 82 = 218 - expect(await gwt.balanceOf(await dividend.getAddress())).to.equal(218); - - // 周期三的有效质押:signer1 45, signer2 50 - // 周期三的分红池: 100 GWT - // 所以signer1应该能提到 100 * 45 / 95 = 47.36, signer2应该能提到 100 * 50 / 95 = 52.63 - console.log( - "signer1 balance before withdraw: ", - await gwt.balanceOf(signers[1].address) - ); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([3], [await gwt.getAddress()]) - ).wait(); - - // cycle 2 withdraw 82, and cycle 3 withdraw 47, total 129 - expect(await gwt.balanceOf(signers[1].address)).to.equal(129); - - // signer2提取两个周期的分红,应该能提到117+52=169 GWT - await ( - await dividend - .connect(signers[2]) - .withdrawDividends([2, 3], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[2].address)).to.equal(169); - }); - - it("test cycle N", async () => { - const totalDeposit = await dividend.getDepositTokenBalance( - gwt.getAddress() - ); - const currentCycle = await dividend.getCurrentCycleIndex(); - console.log( - "total deposit: ", - totalDeposit, - " current cycle: ", - currentCycle - ); - - const stake1 = await dividend - .connect(signers[1]) - .getStakeAmount(currentCycle); - - // deposit 1 GWT for 5 cycles - for (let i = 0; i < 5; i++) { - mine(1000); - await (await dividend.deposit(1, await gwt.getAddress())).wait(); - - // check stake amount with signer[1] - const currentCycle = await dividend.getCurrentCycleIndex(); - expect( - await dividend.connect(signers[1]).getStakeAmount(currentCycle) - ).to.equal(stake1); - expect( - await dividend.connect(signers[1]).getStakeAmount(currentCycle - 1n) - ).to.equal(stake1); - } - - // check the total deposit amount - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - totalDeposit + 5n - ); - - // get current cycle index - const cycle = await dividend.getCurrentCycleIndex(); - expect(cycle).to.equal(currentCycle + 5n); - - // get current cycle staked amount for signer[1] - const stake1_now = await dividend.connect(signers[1]).getStakeAmount(cycle); - console.log("stake1: ", stake1_now); - - // try unstake extend the limit - await expect( - dividend.connect(signers[1]).unstake(stake1_now + 1n) - ).to.be.revertedWith("Insufficient stake amount"); - - // record the token balance of signer[1] of DMC - const balance1 = await dmc.balanceOf(signers[1].address); - console.log("DMC balance1 of signer[1]: ", balance1); - - // try unstake all - await (await dividend.connect(signers[1]).unstake(stake1_now)).wait(); - - // check balance is right - const balance2 = await dmc.balanceOf(signers[1].address); - console.log("DMC balance2 of signer[1]: ", balance2); - expect(balance2).to.equal(balance1 + stake1_now); - - { - // try withdraw dividends for prev cycle with signer[1], but is zero - const balance = await gwt.balanceOf(signers[1].address); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[1].address)).to.equal(balance); - } - - // stake again with same amount - await (await dividend.connect(signers[1]).stake(stake1_now)).wait(); - - // check balance of gwt in contract for signer[1] - const balance3 = await dmc.balanceOf(signers[1].address); - console.log("DMC balance of signer[1]: ", balance3); - expect(balance3).to.equal(balance1); - - { - // to next cycle - mine(1000); - - // deposit 10 GWT to current cycle - await (await dividend.deposit(10, await gwt.getAddress())).wait(); - - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - totalDeposit + 5n + 10n - ); - - // try withdraw dividends for prev cycle with signer[1] - const balance = await gwt.balanceOf(signers[1].address); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([cycle], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[1].address)).to.equal(balance); - } - - { - // to next cycle - mine(1000); - - // deposit 10 GWT to current cycle - await (await dividend.deposit(10, await gwt.getAddress())).wait(); - - expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( - totalDeposit + 5n + 10n + 10n - ); - - // check stake amount for signer[1] with previous cycle - const cycle = await dividend.getCurrentCycleIndex(); - const stake1 = await dividend - .connect(signers[1]) - .getStakeAmount(cycle - 1n); - - // get stake amount for signer[2] with prev cycle - const stake2 = await dividend - .connect(signers[2]) - .getStakeAmount(cycle - 1n); - - // estimate the dividend amount for signer[1] and signer[2] - const dividend1 = (10n * stake1) / (stake1 + stake2); - const dividend2 = (10n * stake2) / (stake1 + stake2); - - // try withdraw dividends for prev cycle with signer[1] - - // first check dividend is not withdrawed - expect( - await dividend - .connect(signers[1]) - .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) - ).to.equal(false); - - const balance = await gwt.balanceOf(signers[1].address); - await ( - await dividend - .connect(signers[1]) - .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[1].address)).to.equal( - balance + dividend1 - ); - - expect( - await dividend - .connect(signers[1]) - .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) - ).to.equal(true); - - // try withdraw dividends for prev cycle with signer[2] - expect( - await dividend - .connect(signers[2]) - .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) - ).to.equal(false); - - const balance2 = await gwt.balanceOf(signers[2].address); - await ( - await dividend - .connect(signers[2]) - .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) - ).wait(); - expect(await gwt.balanceOf(signers[2].address)).to.equal( - balance2 + dividend2 - ); - - expect( + let dmc: DMC; + let gwt: GWT; + //let dividend: Dividend2; + let dividend: DividendContract; + let signers: HardhatEthersSigner[]; + + before(async () => { + signers = await ethers.getSigners(); + + dmc = await ( + await ethers.deployContract("DMC", [ + ethers.parseEther("1000000000"), + [signers[0].address], + [1000000], + ]) + ).waitForDeployment(); + gwt = await (await ethers.deployContract("GWT", [[],[]])).waitForDeployment(); + //dividend = await (await ethers.deployContract("Dividend2", [await dmc.getAddress(), 1000])).waitForDeployment() + + // add init token address as white list, address(0) and gwt token address + const tokenWhiteList = [ + await gwt.getAddress(), + "0x0000000000000000000000000000000000000000", + ]; + + dividend = (await ( + await upgrades.deployProxy( + await ethers.getContractFactory("DividendContract"), + [await dmc.getAddress(), 1000, tokenWhiteList] + ) + ).waitForDeployment()) as unknown as DividendContract; + + // 给signers[0] 1000个GWT + await (await gwt.enableMinter([signers[0].address])).wait(); + await (await gwt.mint(signers[0].address, 10000)).wait(); + await (await gwt.approve(await dividend.getAddress(), 10000)).wait(); + + // 给signers[1]到19, 每人100个DMC + for (let i = 1; i < 3; i++) { + await (await dmc.transfer(signers[i].address, 100)).wait(); + await ( + await dmc.connect(signers[i]).approve(await dividend.getAddress(), 1000) + ).wait(); + } + + // 测试白名单 + await (await dividend.addTokenToWhitelist(await gwt.getAddress())).wait(); + }); + + it("test init", async () => { + // test white list, only owner can add token to white list + dividend.connect(signers[0]).addTokenToWhitelist(await gwt.getAddress()); + + // test not owner + await expect( + dividend.connect(signers[1]).addTokenToWhitelist(await gwt.getAddress()) + ).to.be.reverted; + + // test remove token from white list + await ( + await dividend.removeTokenFromWhitelist(await gwt.getAddress()) + ).wait(); + + // test is in white list + expect( + await dividend.isTokenInWhitelisted(await gwt.getAddress()) + ).to.equal(false); + + // add again + await (await dividend.addTokenToWhitelist(await gwt.getAddress())).wait(); + expect( + await dividend.isTokenInWhitelisted(await gwt.getAddress()) + ).to.equal(true); + + // display the white list + const whiteList = await dividend.getTokenWhitelist(); + console.log("white list: ", whiteList); + }); + + it("test cycle 0", async () => { + // 初始周期0 + expect(await dividend.getCurrentCycleIndex()).to.equal(0); + await dividend.tryNewCycle(); + expect(await dividend.getCurrentCycleIndex()).to.equal(0); + + // error unstake and withdraw test + await expect(dividend.connect(signers[1]).unstake(50)).to.be.revertedWith( + "No stake record found" + ); + await expect( + dividend + .connect(signers[1]) + .withdrawDividends([0], [await gwt.getAddress()]) + ).to.be.revertedWith("Cannot claim current or future cycle"); + + await expect(dividend.connect(signers[0]).unstake(50)).to.be.revertedWith( + "No stake record found" + ); + await expect( + dividend + .connect(signers[0]) + .withdrawDividends([0, 1, 2], [await gwt.getAddress()]) + ).to.be.revertedWith("Cannot claim current or future cycle"); + + // test getStakeAmount with signer[0] + expect(await dividend.connect(signers[0]).getStakeAmount(0)).to.equal(0); + await expect( + dividend.connect(signers[0]).getStakeAmount(1) + ).to.be.revertedWith("Invalid cycle index"); + + await expect( + dividend.connect(signers[1]).getStakeAmount(10) + ).to.be.revertedWith("Invalid cycle index"); + }); + + it("test cycle 1", async () => { + mine(2, { interval: 1000 }); + expect(await dividend.getCurrentCycleIndex()).to.equal(0); + + { + // check the token balance is 0 + await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + 0 + ); + + // 打入100 GWT, 前进到周期1 + await (await dividend.deposit(90, await gwt.getAddress())).wait(); + + await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + 90 + ); + + // direct transfer to dividend contract + await (await gwt.transfer(await dividend.getAddress(), 10)).wait(); + await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + 100 + ); + } + + expect(await dividend.getCurrentCycleIndex()).to.equal(1); + + // check stake amount with signer[1] + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(0); + await expect( + dividend.connect(signers[1]).getStakeAmount(2) + ).to.be.revertedWith("Invalid cycle index"); + + // 第1周期,signers1,2分别stake 50 DMC + await (await dividend.connect(signers[1]).stake(50)).wait(); + await (await dividend.connect(signers[2]).stake(50)).wait(); + + // check dmc balance for signer[1] and signer[2] + expect(await dmc.balanceOf(signers[1].address)).to.equal(50); + expect(await dmc.balanceOf(signers[2].address)).to.equal(50); + + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[2]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); + await expect( + dividend.connect(signers[2]).getStakeAmount(2) + ).to.be.revertedWith("Invalid cycle index"); + + // test withdraw dividends with cycle 0 + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([0], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[1].address)).to.equal(0); + + // test withdraw dividends with cycle 1 with revert + await expect( + dividend + .connect(signers[1]) + .withdrawDividends([1], [await gwt.getAddress()]) + ).to.be.revertedWith("Cannot claim current or future cycle"); + + await expect( + dividend + .connect(signers[1]) + .withdrawDividends([2], [await gwt.getAddress()]) + ).to.be.revertedWith("Cannot claim current or future cycle"); + + // test withdraw dividends with unknown tokens + // nothing to withdraw + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([0], [await signers[1].address]) + ).wait(); + }); + + it("test cycle 2", async () => { + // 又打入100 GWT,前进到周期2, 此时总分红200 GWT,因为周期1没有完整的抵押,所以周期1的分红是提不到的 + mine(2, { interval: 1000 }); + await (await dividend.deposit(100, await gwt.getAddress())).wait(); + + // check stake amount with signer[1] and signer[2] + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(50); + + expect(await dividend.connect(signers[2]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); + + // 因为周期1开始时没有已确定的抵押,周期1的分红是提不到的 + const balance = await gwt.balanceOf(signers[1].address); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([1], [await gwt.getAddress()]) + ).wait(); + + const afterBalance = await gwt.balanceOf(signers[1].address); + expect(balance).to.equal(afterBalance); + + // withdraw with error cycle + await expect( + dividend + .connect(signers[1]) + .withdrawDividends([2], [await gwt.getAddress()]) + ).to.be.revertedWith("Cannot claim current or future cycle"); + + // withdraw with no stake + await ( + await dividend + .connect(signers[3]) + .withdrawDividends([1, 0], [await gwt.getAddress()]) + ).wait(); + const balance2 = await gwt.balanceOf(signers[3].address); + expect(balance2).to.equal(0); + + // stake and unstake only on current cycle + { + await (await dividend.connect(signers[1]).stake(20)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(30); + + // check stake amount with signer[1] + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); + + await (await dividend.connect(signers[1]).unstake(15)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(45); + + // check stake amount with signer[1] + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(55); + + await (await dividend.connect(signers[1]).unstake(5)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(50); + + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(50); + } + + { + // test error stake + await expect(dividend.connect(signers[1]).stake(0)).to.be.revertedWith( + "Cannot stake 0 DMC" + ); + } + + { + // test error unstake + await expect( + dividend.connect(signers[1]).unstake(100) + ).to.be.revertedWith("Insufficient stake amount"); + + await expect(dividend.connect(signers[1]).unstake(0)).to.be.revertedWith( + "Cannot unstake 0" + ); + } + + { + // test stake and unstake with effect prev cycle + await (await dividend.connect(signers[1]).stake(20)).wait(); + await (await dividend.connect(signers[1]).stake(10)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(20); + + await (await dividend.connect(signers[1]).unstake(45)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(65); + + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(35); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(35); + + await (await dividend.connect(signers[1]).stake(35)).wait(); + expect(await dmc.balanceOf(signers[1].address)).to.equal(30); + expect(await dividend.connect(signers[1]).getStakeAmount(0)).to.equal(0); + expect(await dividend.connect(signers[1]).getStakeAmount(1)).to.equal(35); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); + } + }); + + it("test cycle 3", async () => { + // 前进到周期3,周期2的分红200 GWT,周期3的分红100 GWT + mine(2, { interval: 1500 }); + await (await dividend.deposit(100, await gwt.getAddress())).wait(); + + // check cycle is 3 now + expect(await dividend.getCurrentCycleIndex()).to.equal(3); + + // cycle 2, total stake 50 + 35 = 85, singer1 stake 35, should get 200 * 35 / 85 = 82 + // and signer2 stake 50, should get 200 * 50 / 85 = 117.6 + + // check full stake amount for signer[1] and signer[2] in cycle 2 + expect(await dividend.connect(signers[1]).getStakeAmount(2 - 1)).to.equal( + 35 + ); + expect(await dividend.connect(signers[2]).getStakeAmount(2 - 1)).to.equal( + 50 + ); + + // record the token balance of the contract + let balance_prev; + { + balance_prev = BigInt( + await dividend.getDepositTokenBalance(gwt.getAddress()) + ); + console.log("balance_prev: ", balance_prev); + + // try update once + await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + balance_prev + ); + } + + // test withdraw dividends with cycle 2 for signer[1] + expect( + await dividend + .connect(signers[1]) + .isDividendWithdrawed(2, await gwt.getAddress()) + ).to.equal(false); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([2], [await gwt.getAddress()]) + ).wait(); + expect( + await dividend + .connect(signers[1]) + .isDividendWithdrawed(2, await gwt.getAddress()) + ).to.equal(true); + expect(await gwt.balanceOf(signers[1].address)).to.equal(82); + + // verify the token balance of the contract after withdraw + { + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + balance_prev - 82n + ); + await (await dividend.updateTokenBalance(await gwt.getAddress())).wait(); + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + balance_prev - 82n + ); + } + + // test withdraw second time with cycle 2 for signer[1], will be reverted + await expect( + dividend + .connect(signers[1]) + .withdrawDividends([2], [await gwt.getAddress()]) + ).to.be.revertedWith("Already claimed"); + + await expect( + dividend + .connect(signers[1]) + .withdrawDividends( + [2], + [await gwt.getAddress(), "0x0000000000000000000000000000000000000000"] + ) + ).to.be.revertedWith("Already claimed"); + + // 周期3,signer1先存20, 再提取45 DMC出来, 所以周期3的质押实际上是减少了25, 70-25=45 + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(70); + + // print total balance of stake token in contract + const balance = await dmc.balanceOf(await dividend.getAddress()); + console.log("total stake amount of DMC in contract: ", balance); + + // check balance with getTotalStaked with current cycle + expect( + await dividend.getTotalStaked(await dividend.getCurrentCycleIndex()) + ).to.equal(balance); + expect(balance).to.equal(120); + + await (await dividend.connect(signers[1]).stake(20)).wait(); + + const balance2 = await dmc.balanceOf(await dividend.getAddress()); + console.log( + "total stake amount of DMC in contract after stake: ", + balance2 + ); + expect( + await dividend.getTotalStaked(await dividend.getCurrentCycleIndex()) + ).to.equal(balance2); + expect(balance2).to.equal(140); + + await (await dividend.connect(signers[1]).unstake(45)).wait(); + expect(await dividend.connect(signers[1]).getStakeAmount(2)).to.equal(45); + + // test withdraw dividends with cycle 2 for signer[2], witch stake amount is 50 and should get 117 + expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); + await (await dividend.connect(signers[2]).stake(10)).wait(); + await (await dividend.connect(signers[2]).unstake(9)).wait(); + await (await dividend.connect(signers[2]).unstake(1)).wait(); + expect(await dividend.connect(signers[2]).getStakeAmount(1)).to.equal(50); + expect(await dividend.connect(signers[2]).getStakeAmount(2)).to.equal(50); + + /* await dividend .connect(signers[2]) - .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) - ).to.equal(true); - } - }); + .withdrawDividends([2], [await gwt.getAddress()]); + expect(await gwt.balanceOf(signers[2].address)).to.equal(117); + */ + }); + + it("test cycle 4", async () => { + // 强制结算周期3,进入周期4 + mine(2, { interval: 1000 }); + await (await dividend.tryNewCycle()).wait(); + + // check gwt balance of the contract + // 300 - 82 = 218 + expect(await gwt.balanceOf(await dividend.getAddress())).to.equal(218); + + // 周期三的有效质押:signer1 45, signer2 50 + // 周期三的分红池: 100 GWT + // 所以signer1应该能提到 100 * 45 / 95 = 47.36, signer2应该能提到 100 * 50 / 95 = 52.63 + console.log( + "signer1 balance before withdraw: ", + await gwt.balanceOf(signers[1].address) + ); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([3], [await gwt.getAddress()]) + ).wait(); + + // cycle 2 withdraw 82, and cycle 3 withdraw 47, total 129 + expect(await gwt.balanceOf(signers[1].address)).to.equal(129); + + // signer2提取两个周期的分红,应该能提到117+52=169 GWT + await ( + await dividend + .connect(signers[2]) + .withdrawDividends([2, 3], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[2].address)).to.equal(169); + }); + + it("test cycle N", async () => { + const totalDeposit = await dividend.getDepositTokenBalance( + gwt.getAddress() + ); + const currentCycle = await dividend.getCurrentCycleIndex(); + console.log( + "total deposit: ", + totalDeposit, + " current cycle: ", + currentCycle + ); + + const stake1 = await dividend + .connect(signers[1]) + .getStakeAmount(currentCycle); + + // deposit 1 GWT for 5 cycles + for (let i = 0; i < 5; i++) { + mine(2, { interval: 1000 }); + await (await dividend.deposit(1, await gwt.getAddress())).wait(); + + // check stake amount with signer[1] + const currentCycle = await dividend.getCurrentCycleIndex(); + expect( + await dividend.connect(signers[1]).getStakeAmount(currentCycle) + ).to.equal(stake1); + expect( + await dividend.connect(signers[1]).getStakeAmount(currentCycle - 1n) + ).to.equal(stake1); + } + + // check the total deposit amount + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + totalDeposit + 5n + ); + + // get current cycle index + const cycle = await dividend.getCurrentCycleIndex(); + expect(cycle).to.equal(currentCycle + 5n); + + // get current cycle staked amount for signer[1] + const stake1_now = await dividend.connect(signers[1]).getStakeAmount(cycle); + console.log("stake1: ", stake1_now); + + // try unstake extend the limit + await expect( + dividend.connect(signers[1]).unstake(stake1_now + 1n) + ).to.be.revertedWith("Insufficient stake amount"); + + // record the token balance of signer[1] of DMC + const balance1 = await dmc.balanceOf(signers[1].address); + console.log("DMC balance1 of signer[1]: ", balance1); + + // try unstake all + await (await dividend.connect(signers[1]).unstake(stake1_now)).wait(); + + // check balance is right + const balance2 = await dmc.balanceOf(signers[1].address); + console.log("DMC balance2 of signer[1]: ", balance2); + expect(balance2).to.equal(balance1 + stake1_now); + + { + // try withdraw dividends for prev cycle with signer[1], but is zero + const balance = await gwt.balanceOf(signers[1].address); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[1].address)).to.equal(balance); + } + + // stake again with same amount + await (await dividend.connect(signers[1]).stake(stake1_now)).wait(); + + // check balance of gwt in contract for signer[1] + const balance3 = await dmc.balanceOf(signers[1].address); + console.log("DMC balance of signer[1]: ", balance3); + expect(balance3).to.equal(balance1); + + { + // to next cycle + mine(2, { interval: 1000 }); + + // deposit 10 GWT to current cycle + await (await dividend.deposit(10, await gwt.getAddress())).wait(); + + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + totalDeposit + 5n + 10n + ); + + // try withdraw dividends for prev cycle with signer[1] + const balance = await gwt.balanceOf(signers[1].address); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([cycle], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[1].address)).to.equal(balance); + } + + { + // to next cycle + mine(2, { interval: 1000 }); + + // deposit 10 GWT to current cycle + await (await dividend.deposit(10, await gwt.getAddress())).wait(); + + expect(await dividend.getDepositTokenBalance(gwt.getAddress())).to.equal( + totalDeposit + 5n + 10n + 10n + ); + + // check stake amount for signer[1] with previous cycle + const cycle = await dividend.getCurrentCycleIndex(); + const stake1 = await dividend + .connect(signers[1]) + .getStakeAmount(cycle - 1n); + + // get stake amount for signer[2] with prev cycle + const stake2 = await dividend + .connect(signers[2]) + .getStakeAmount(cycle - 1n); + + // estimate the dividend amount for signer[1] and signer[2] + const dividend1 = (10n * stake1) / (stake1 + stake2); + const dividend2 = (10n * stake2) / (stake1 + stake2); + + // try withdraw dividends for prev cycle with signer[1] + + // first check dividend is not withdrawed + expect( + await dividend + .connect(signers[1]) + .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) + ).to.equal(false); + + const balance = await gwt.balanceOf(signers[1].address); + await ( + await dividend + .connect(signers[1]) + .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[1].address)).to.equal( + balance + dividend1 + ); + + expect( + await dividend + .connect(signers[1]) + .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) + ).to.equal(true); + + // try withdraw dividends for prev cycle with signer[2] + expect( + await dividend + .connect(signers[2]) + .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) + ).to.equal(false); + + const balance2 = await gwt.balanceOf(signers[2].address); + await ( + await dividend + .connect(signers[2]) + .withdrawDividends([cycle - 1n], [await gwt.getAddress()]) + ).wait(); + expect(await gwt.balanceOf(signers[2].address)).to.equal( + balance2 + dividend2 + ); + + expect( + await dividend + .connect(signers[2]) + .isDividendWithdrawed(cycle - 1n, await gwt.getAddress()) + ).to.equal(true); + } + }); });