/* Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 */ import { DODOContext, getDODOContext } from './utils/DVMContext'; import { decimalStr, MAX_UINT256 } from './utils/Converter'; // import * as assert from "assert" import { newContract, DODO_TOKEN_CONTRACT_NAME, LOCKED_TOKEN_VAULT_CONTRACT_NAME } from './utils/Contracts'; import { Contract } from 'web3-eth-contract'; import * as assert from 'assert'; import BigNumber from 'bignumber.js'; import { logGas } from './utils/Log'; let DODOToken: Contract let LockedTokenVault: Contract let initTime: any let u1: string let u2: string let u3: string async function init(ctx: DODOContext): Promise { u1 = ctx.spareAccounts[0]; u2 = ctx.spareAccounts[1]; u3 = ctx.spareAccounts[2]; initTime = (await ctx.Web3.eth.getBlock(await ctx.Web3.eth.getBlockNumber())).timestamp; DODOToken = await newContract(DODO_TOKEN_CONTRACT_NAME) // release after 1 day, cliff 10% and vest in 1 day LockedTokenVault = await newContract(LOCKED_TOKEN_VAULT_CONTRACT_NAME, [DODOToken.options.address, initTime + 86400, 86400, decimalStr("0.1")]) DODOToken.methods.approve(LockedTokenVault.options.address, MAX_UINT256).send(ctx.sendParam(ctx.Deployer)) LockedTokenVault.methods.deposit(decimalStr("10000")).send(ctx.sendParam(ctx.Deployer)) } describe("Lock DODO Token", () => { let snapshotId: string let ctx: DODOContext before(async () => { ctx = await getDODOContext() await init(ctx); }) beforeEach(async () => { snapshotId = await ctx.EVM.snapshot(); }); afterEach(async () => { await ctx.EVM.reset(snapshotId) }); describe("Lock operations", () => { it("init states", async () => { assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("10000")) await logGas(LockedTokenVault.methods.grant( [u1], [decimalStr("100")] ), ctx.sendParam(ctx.Deployer), "grant 1 address") }) it("grant", async () => { await logGas(LockedTokenVault.methods.grant( [u1, u2, u3], [decimalStr("100"), decimalStr("200"), decimalStr("300")] ), ctx.sendParam(ctx.Deployer), "grant 3 address") assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("9400")) assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100")) assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), decimalStr("200")) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") await ctx.EVM.increaseTime(86400) assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("10"))) await ctx.EVM.increaseTime(30000) assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("41.25"))) }) it("claim", async () => { await LockedTokenVault.methods.grant( [u1, u2, u3], [decimalStr("100"), decimalStr("200"), decimalStr("300")] ).send(ctx.sendParam(ctx.Deployer)) await ctx.EVM.increaseTime(86400) await LockedTokenVault.methods.claim().send(ctx.sendParam(u1)) assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100")) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("10"))) await ctx.EVM.increaseTime(30000) await LockedTokenVault.methods.claim().send(ctx.sendParam(u1)) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u1).call(), decimalStr("58.75"))) assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("41.25"))) await LockedTokenVault.methods.claim().send(ctx.sendParam(u2)) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0") assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("117.5"))) assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("82.5"))) }) it("recall & transfer", async () => { await LockedTokenVault.methods.grant( [u1, u2, u3], [decimalStr("100"), decimalStr("200"), decimalStr("300")] ).send(ctx.sendParam(ctx.Deployer)) // recall u2 await LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer)) assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), "0") // transfer from u3 to u2 await ctx.EVM.increaseTime(86400 + 30000) await LockedTokenVault.methods.transferLockedToken(u2).send(ctx.sendParam(u3)) await LockedTokenVault.methods.claim().send(ctx.sendParam(u2)) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0") assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("176.25"))) assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("123.75"))) // transfer from u2 to u3 await ctx.EVM.increaseTime(30000) await LockedTokenVault.methods.transferLockedToken(u3).send(ctx.sendParam(u2)) await LockedTokenVault.methods.claim().send(ctx.sendParam(u3)) assert.equal(await LockedTokenVault.methods.getClaimableBalance(u3).call(), "0") assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u3).call(), decimalStr("82.5"))) assert.ok(approxEqual(await DODOToken.methods.balanceOf(u3).call(), decimalStr("93.75"))) // transfer from u3 to u1 await LockedTokenVault.methods.transferLockedToken(u1).send(ctx.sendParam(u3)) }) it("withdraw", async () => { await LockedTokenVault.methods.grant( [u1, u2, u3], [decimalStr("100"), decimalStr("200"), decimalStr("300")] ).send(ctx.sendParam(ctx.Deployer)) await LockedTokenVault.methods.withdraw(decimalStr("1000")).send(ctx.sendParam(ctx.Deployer)) assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("8400")) await assert.rejects( LockedTokenVault.methods.withdraw(decimalStr("8500")).send(ctx.sendParam(ctx.Deployer)), /SUB_ERROR/ ) }) it("finish distributed", async () => { await LockedTokenVault.methods.grant( [u1, u2, u3], [decimalStr("100"), decimalStr("200"), decimalStr("300")] ).send(ctx.sendParam(ctx.Deployer)) await LockedTokenVault.methods.finishDistribute().send(ctx.sendParam(ctx.Deployer)) // can not recall await assert.rejects( LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer)), /DISTRIBUTE FINISHED/ ) }) }) }) function approxEqual(numStr1: string, numStr2: string) { let num1 = new BigNumber(numStr1) let num2 = new BigNumber(numStr2) let ratio = num1.div(num2).minus(1).abs() if (ratio.isLessThan(0.0002)) { return true } else { return false } }