import chai, { expect } from 'chai'; import { 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, AddressZero } from './utils' chai.use(solidity); describe("Election vote tests", () => { 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 rewardCoef = 30e4; 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(); const signer0 = await signers[0].getAddress() const signer1 = await signers[1].getAddress() await token.transfer(signer1, oneToken.mul(1e6)) 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) await slasher.init(signer0, signer1, stake.address, majorCandidates.address, oneToken.mul(5000), 10 * 60, 1e6, 30e4, 30e4, 20e4) const manifest = 'candidate manifest' const amount = oneToken.mul(1000) await token.approve(stake.address, amount) await stake.registerAndStake(amount, manifest) await stake.setVoteRewardCoef(rewardCoef) }); it('voter vote', async () => { const amount = oneToken.mul(1000) await token.connect(signers[1]).approve(election.address, amount) const candidate = await signers[0].getAddress() const signer1 = await signers[1].getAddress() await election.connect(signers[1]).vote(candidate, signer1, amount, AddressZero, 10) const voter = await election.voters(candidate, signer1) expect(voter.amount.eq(amount), 'invalid vote action') const majors = await majorCandidates.majorCandidateList() expect(majors.length != 0, 'invalid vote action') }); }); describe("Election reward tests", () => { 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 rewardCoef = 30e4; 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(); const signer0 = await signers[0].getAddress() const signer1 = await signers[1].getAddress() await token.transfer(signer1, oneToken.mul(1e6)) 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) await slasher.init(signer0, signer1, stake.address, majorCandidates.address, oneToken.mul(5000), 10 * 60, 1e6, 30e4, 30e4, 20e4) const manifest = 'candidate manifest' const amount = oneToken.mul(1000) await token.approve(stake.address, amount) await stake.registerAndStake(amount, manifest) await stake.setVoteRewardCoef(rewardCoef) const votes = oneToken.mul(1000) await token.connect(signers[1]).approve(election.address, votes) await election.connect(signers[1]).vote(signer0, signer1, votes, AddressZero, 10) }); it('voter pending reward', async () => { const timeToAdd = 10 await increaseTime(timeToAdd) const signer0 = await signers[0].getAddress() const signer1 = await signers[1].getAddress() const pendingAllocation = await stake.pendingVoterAllocation(signer0) const voterPending = await election.pendingReward(signer0, signer1) expect(pendingAllocation.eq(voterPending), 'invalid pending reward') }); it('voter claim reward', async () => { const timeToAdd = 10 await increaseTime(timeToAdd) const signer0 = await signers[0].getAddress() const signer1 = await signers[1].getAddress() const blanceBefore = await token.balanceOf(signer1) const voterPending = await election.pendingReward(signer0, signer1) await election.connect(signers[1]).claim(signer0, signer1) const blanceAfter = await token.balanceOf(signer1) expect(blanceAfter.sub(blanceBefore).eq(voterPending), 'invalid claimed reward') }); it('voter withdraw and claim', async () => { const timeToAdd = 10 const amount = oneToken.mul(900) await increaseTime(timeToAdd) const signer0 = await signers[0].getAddress() const signer1 = await signers[1].getAddress() const blanceBefore = await token.balanceOf(signer1) const voterPending = await election.pendingReward(signer0, signer1) await election.connect(signers[1]).withdrawAndClaim(signer0, amount, signer1, signer0, 10) const blanceAfter = await token.balanceOf(signer1) expect(blanceAfter.sub(blanceBefore).eq(voterPending.add(amount)), 'invalid claimed reward') }); }); describe("Election update votes", () => { 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) const amount = oneToken.mul(1000) let last = '' for (let i = 0; i < 10; i++) { const signer = await signers[i].getAddress() await token.transfer(signer, oneToken.mul(1e6)) await token.connect(signers[i]).approve(stake.address, amount) const manifest = `candidate manifest ${i}` await stake.connect(signers[i]).registerAndStake(amount, manifest) const votes = oneToken.mul((10 - i) * 100) await token.connect(signers[i]).approve(election.address, votes) await election.connect(signers[i]).vote(signer, signer, votes, !!last ? last : AddressZero, 10) last = signer } }); it('election vote', async () => { const votes = oneToken.mul(1000) const tail = await majorCandidates.tailCandidate() await token.approve(election.address, votes) const signer = await signers[0].getAddress() await election.vote(tail, signer, votes, tail, 10) const head = await majorCandidates.headCandidate() expect(head == tail, 'invalid vote'); }); it('election withdraw and claim', async () => { const votes = oneToken.mul(499) const signer = await signers[0].getAddress() await election.withdrawAndClaim(signer, votes, signer, signer, 10) }); });