Cover DioneStaking by 100% with unit tests

This commit is contained in:
ChronosX88 2021-04-28 23:13:22 +03:00
parent 8a07edcb06
commit e0f004ea5d
Signed by: ChronosXYZ
GPG Key ID: 085A69A82C8C511A
2 changed files with 220 additions and 1 deletions

View File

@ -1,3 +1,3 @@
module.exports = { module.exports = {
skipFiles: ['Timelock.sol', 'Mediator.sol', 'vendor/Ownable.sol'] skipFiles: ['Timelock.sol', 'Mediator.sol', 'vendor/Ownable.sol', 'DioneToken.sol']
}; };

View File

@ -0,0 +1,219 @@
import { BigNumber } from "@ethersproject/bignumber";
import { Contract } from "@ethersproject/contracts";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";
import { expect } from "chai";
import { ethers } from "hardhat";
describe("DioneStaking", () => {
let signers: SignerWithAddress[];
let allSigners: SignerWithAddress[];
let dioneToken: Contract;
let dioneStaking: Contract;
const rewardAmount = 100;
const minStakeAmount = 500;
beforeEach(async () => {
allSigners = await ethers.getSigners();
signers = allSigners.slice(0, 4);
const DioneToken = await ethers.getContractFactory("DioneToken");
const DioneStaking = await ethers.getContractFactory("DioneStaking");
dioneToken = await DioneToken.deploy();
await dioneToken.deployed();
dioneStaking = await DioneStaking.deploy(
dioneToken.address,
toWei(rewardAmount),
0,
toWei(minStakeAmount)
);
await dioneStaking.deployed();
for (var s of signers) {
await dioneToken.mint(s.address, toWei(5000));
}
await dioneToken.transferOwnership(dioneStaking.address);
});
it("should successfully stake some of tokens", async () => {
for (var s of signers) {
await dioneToken.connect(s).approve(dioneStaking.address, toWei(666));
await expect(dioneStaking.connect(s).stake(toWei(666)))
.to.emit(dioneStaking, "Stake")
.withArgs(s.address, toWei(666));
expect(await dioneStaking.minerStake(s.address))
.to.be.equal(toWei(666));
expect(await dioneStaking.isMiner(s.address))
.to.be.equal(true);
}
});
it("check miner balance without stake", async () => {
expect(await dioneStaking.minerStake(signers[0].address))
.to.be.equal(toWei(0));
expect(await dioneStaking.isMiner(signers[0].address))
.to.be.equal(false);
});
it("should mine reward successfully", async () => {
await dioneStaking.setOracleContractAddress(signers[0].address)
await dioneToken.approve(dioneStaking.address, toWei(500));
await dioneStaking.stake(toWei(500));
const res = await dioneStaking.mine(signers[0].address);
await expect(res)
.to.emit(dioneStaking, "Mine")
.withArgs(signers[0].address, res.blockNumber);
expect(await dioneToken.balanceOf(signers[0].address))
.to.be.equal(toWei(4600));
});
it("should mine and stake reward successfully", async () => {
await dioneStaking.setOracleContractAddress(signers[0].address);
await dioneToken.approve(dioneStaking.address, toWei(500));
await dioneStaking.stake(toWei(500));
await dioneStaking.mineAndStake(signers[0].address);
expect(await dioneStaking.minerStake(signers[0].address))
.to.be.equal(toWei(600));
});
it("should fail if caller of mine methods isn't desired address", async () => {
await expect(dioneStaking.mine(signers[0].address))
.to.be.revertedWith("not oracle contract");
await expect(dioneStaking.mineAndStake(signers[0].address))
.to.be.revertedWith("not oracle contract");
});
it("check change of total stake after staking", async () => {
const expectedTotalStake = toWei(666*4);
for (var s of signers) {
await dioneToken.connect(s).approve(dioneStaking.address, toWei(666));
await dioneStaking.connect(s).stake(toWei(666));
}
expect(await dioneStaking.totalStake())
.to.be.equal(expectedTotalStake);
});
it("should withdraw funds successfully", async () => {
for (var s of signers) {
await dioneToken.connect(s).approve(dioneStaking.address, toWei(500));
await dioneStaking.connect(s).stake(toWei(500));
}
for (var s of signers) {
await expect(dioneStaking.connect(s).withdraw(toWei(500)))
.to.emit(dioneStaking, "Withdraw")
.withArgs(s.address, toWei(500));
expect(await dioneToken.balanceOf(s.address))
.to.be.equal(toWei(5000));
}
});
it("should fail withdrawing invalid values", async () => {
await dioneToken.approve(dioneStaking.address, toWei(500));
await dioneStaking.stake(toWei(500));
await expect(dioneStaking.withdraw(toWei(666)))
.to.be.revertedWith("withdraw: not enough tokens");
await expect(dioneStaking.withdraw(0))
.to.be.revertedWith("cannot withdraw zero");
});
it("check changing miner reward", async () => {
await expect(dioneStaking.setMinerReward(0))
.to.be.revertedWith("reward must not be zero");
await expect(dioneStaking.setMinerReward(toWei(5)))
.to.emit(dioneStaking, "RewardChanged")
.withArgs(toWei(100), toWei(5));
expect(await dioneStaking.minerReward())
.to.be.equal(toWei(5));
await expect(dioneStaking.connect(signers[1]).setMinerReward(toWei(5)))
.to.be.revertedWith("Ownable: caller is not the owner");
});
it("check changing minimum stake", async () => {
await expect(dioneStaking.setMinimumStake(0))
.to.be.revertedWith("minimum stake must not be zero");
await expect(dioneStaking.setMinimumStake(toWei(5)))
.to.emit(dioneStaking, "MinimumStakeChanged")
.withArgs(toWei(500), toWei(5));
expect(await dioneStaking.minimumStake())
.to.be.equal(toWei(5));
await expect(dioneStaking.connect(signers[1]).setMinimumStake(toWei(5)))
.to.be.revertedWith("Ownable: caller is not the owner");
});
it("should fail when staking invalid values", async () => {
await expect(dioneStaking.stake(0))
.to.be.revertedWith("cannot stake zero");
await expect(dioneStaking.stake(toWei(400)))
.to.be.revertedWith("actual stake amount is less than minimum stake amount");
});
it("should fail when calling slashMiner with invalid values (initial checks)", async () => {
const zeroAddress = "0x0000000000000000000000000000000000000000";
await expect(dioneStaking.slashMiner(zeroAddress, [signers[0].address]))
.to.be.revertedWith("caller is not the dispute contract");
await dioneStaking.setDisputeContractAddress(signers[0].address);
await expect(dioneStaking.slashMiner(zeroAddress, [signers[0].address]))
.to.be.revertedWith("slashing address must not be zero");
await expect(dioneStaking.slashMiner(signers[1].address, [signers[0].address]))
.to.be.revertedWith("slashing address isn't dione miner");
for (var s of signers) {
await dioneToken.connect(s).approve(dioneStaking.address, toWei(500));
await dioneStaking.connect(s).stake(toWei(500));
}
await expect(dioneStaking.slashMiner(signers[1].address, [signers[0].address, signers[2].address, allSigners[4].address]))
.to.be.revertedWith("receipent address isn't dione miner");
await expect(dioneStaking.slashMiner(signers[1].address, [signers[0].address, signers[2].address, signers[1].address]))
.to.be.revertedWith("receipent address must not be slashing address");
});
it("should fail set*Address methods when passing invalid values", async () => {
const zeroAddress = "0x0000000000000000000000000000000000000000";
await expect(dioneStaking.setDisputeContractAddress(zeroAddress))
.to.be.revertedWith("address must not be zero");
await expect(dioneStaking.setOracleContractAddress(zeroAddress))
.to.be.revertedWith("address must not be zero");
});
it("should stake few time successfully", async () => {
const expectedStake = toWei(500*3);
for (var i = 0; i < 3; i++) {
await dioneToken.approve(dioneStaking.address, toWei(500));
await dioneStaking.stake(toWei(500));
}
expect(await dioneStaking.minerStake(signers[0].address))
.to.be.equal(expectedStake);
});
})
function toWei(eth: number): BigNumber {
return ethers.constants.WeiPerEther.mul(eth);
}