import chai, { expect } from 'chai'; import { BigNumber, Signer } from 'ethers'; import { solidity } from 'ethereum-waffle'; import { ethers } from 'hardhat'; import { MockToken, MockToken__factory, MockStake, MockStake__factory, MockRewarder, MockRewarder__factory, MockElection, MockElection__factory, MockMajorCandidates, MockMajorCandidates__factory, MockSlasher, MockSlasher__factory } from '../types'; import { oneToken, increaseTime } from './utils' chai.use(solidity); describe('Stake register and stake', () => { let signers: Signer[]; let token: MockToken; let stake: MockStake; let rewarder: MockRewarder; let election: MockElection; let slasher: MockSlasher; let majorCandidates: MockMajorCandidates; const rewardPerSecond = oneToken.mul(40) beforeEach(async () => { signers = await ethers.getSigners(); token = await new MockToken__factory(signers[0]).deploy(); stake = await new MockStake__factory(signers[0]).deploy(); rewarder = await new MockRewarder__factory(signers[0]).deploy(); election = await new MockElection__factory(signers[0]).deploy(); majorCandidates = await new MockMajorCandidates__factory(signers[0]).deploy(); slasher = await new MockSlasher__factory(signers[0]).deploy(); await token.transfer(rewarder.address, oneToken.mul(1e7)) await rewarder.init(token.address, [stake.address, election.address]) await stake.init(token.address, rewarder.address, election.address, majorCandidates.address, slasher.address, 60 * 10, 100, rewardPerSecond) await election.init(token.address, rewarder.address, stake.address, majorCandidates.address) await majorCandidates.init(stake.address, election.address) }); it('candidate register', async () => { const signer = await signers[0].getAddress() const manifest = 'candidate manifest' await stake.register('manifest') const candidate = await stake.candidateInfo(signer) expect(candidate.manifest == manifest, 'invalid candidate manifest') expect(candidate.grade == 2, 'invalid candidate grade') }); it('candidate register and stake', async () => { const signer = await signers[0].getAddress() const manifest = 'candidate manifest' const amount = oneToken.mul(1000) await token.approve(stake.address, amount) await stake.registerAndStake(amount, manifest) const candidate = await stake.candidateInfo(signer) expect(candidate.amount == amount, 'invalid candidate amount') }); it('candidate get pending reward', async () => { const signer = await signers[0].getAddress() const timeToAdd = 10 await increaseTime(timeToAdd) const pending = await stake.pendingReward(signer) expect(pending.eq(rewardPerSecond.div(4).mul(timeToAdd)), 'invalid reward') }); }); describe('Stake reward', () => { let signers: Signer[]; let token: MockToken; let stake: MockStake; let rewarder: MockRewarder; let election: MockElection; let slasher: MockSlasher; let majorCandidates: MockMajorCandidates; const rewardPerSecond = oneToken.mul(40) const stakeFrozenPeriod = 30; beforeEach(async () => { signers = await ethers.getSigners(); token = await new MockToken__factory(signers[0]).deploy(); stake = await new MockStake__factory(signers[0]).deploy(); rewarder = await new MockRewarder__factory(signers[0]).deploy(); election = await new MockElection__factory(signers[0]).deploy(); majorCandidates = await new MockMajorCandidates__factory(signers[0]).deploy(); slasher = await new MockSlasher__factory(signers[0]).deploy(); await token.transfer(rewarder.address, oneToken.mul(1e7)) await rewarder.init(token.address, [stake.address, election.address]) await stake.init(token.address, rewarder.address, election.address, majorCandidates.address, slasher.address, stakeFrozenPeriod, 100, rewardPerSecond) await election.init(token.address, rewarder.address, stake.address, majorCandidates.address) await majorCandidates.init(stake.address, election.address) const manifest = 'candidate manifest' const amount = oneToken.mul(1000) await token.approve(stake.address, amount) await stake.registerAndStake(amount, manifest) }); it('candidate get pending reward', async () => { const signer = await signers[0].getAddress() const timeToAdd = 10 await increaseTime(timeToAdd) const pending = await stake.pendingReward(signer) expect(pending.eq(rewardPerSecond.div(4).mul(timeToAdd)), 'invalid reward') }); it('candidate claim reward', async () => { const signer = await signers[0].getAddress() const timeToAdd = 10 await increaseTime(timeToAdd) const balanceBefore = await token.balanceOf(signer) const pending = await stake.pendingReward(signer) await stake.claim(signer) const balanceAfter = await token.balanceOf(signer) expect(pending.eq(balanceAfter.sub(balanceBefore)), 'invalid claimed reward') }); it('candidate withdraw and claim', async () => { const signer = await signers[0].getAddress() const timeToAdd = stakeFrozenPeriod+10 await increaseTime(timeToAdd) const balanceBefore = await token.balanceOf(signer) const pending = await stake.pendingReward(signer) const condidate = await stake.candidateInfo(signer) await stake.withdrawAndClaim(condidate.amount, signer) const balanceAfter = await token.balanceOf(signer) expect(pending.add(condidate.amount).eq(balanceAfter.sub(balanceBefore)), 'invalid withdrawal') }); it('candidate quit', async () => { const signer = await signers[0].getAddress() const timeToAdd = stakeFrozenPeriod + 10 await increaseTime(timeToAdd) const balanceBefore = await token.balanceOf(signer) const pending = await stake.pendingReward(signer) const condidate = await stake.candidateInfo(signer) await stake.quit(signer) const balanceAfter = await token.balanceOf(signer) expect(pending.add(condidate.amount).eq(balanceAfter.sub(balanceBefore)), 'invalid withdrawal') }); });