Skip to content

Commit

Permalink
test: coverage of delayed stakes
Browse files Browse the repository at this point in the history
  • Loading branch information
jaybuidl committed Dec 9, 2023
1 parent 6942179 commit 236d1d3
Showing 1 changed file with 88 additions and 44 deletions.
132 changes: 88 additions & 44 deletions contracts/test/arbitration/staking.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ethers, getNamedAccounts, network, deployments } from "hardhat";
const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs");
import { BigNumber } from "ethers";
import {
PNK,
Expand All @@ -15,8 +16,8 @@ import exp from "constants";
/* eslint-disable no-unused-expressions */

describe("Staking", async () => {
const ONE_TENTH_ETH = BigNumber.from(10).pow(17);
const ONE_THOUSAND_PNK = BigNumber.from(10).pow(21);
const ETH = (amount: number) => ethers.utils.parseUnits(amount.toString());
const PNK = ETH;

// 2nd court, 3 jurors, 1 dispute kit
const extraData =
Expand Down Expand Up @@ -49,13 +50,13 @@ describe("Staking", async () => {

const reachDrawingPhase = async () => {
expect(await sortition.phase()).to.be.equal(0); // Staking
const arbitrationCost = ONE_TENTH_ETH.mul(3);
const arbitrationCost = ETH(0.1).mul(3);

await core.createCourt(1, false, ONE_THOUSAND_PNK, 1000, ONE_TENTH_ETH, 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit
await core.createCourt(1, false, PNK(1000), 1000, ETH(0.1), 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit

await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(4));
await core.setStake(1, ONE_THOUSAND_PNK.mul(2));
await core.setStake(2, ONE_THOUSAND_PNK.mul(2));
await pnk.approve(core.address, PNK(4000));
await core.setStake(1, PNK(2000));
await core.setStake(2, PNK(2000));

expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([BigNumber.from("1"), BigNumber.from("2")]);

Expand All @@ -73,6 +74,13 @@ describe("Staking", async () => {
balanceBefore = await pnk.balanceOf(deployer);
};

const reachStakingPhaseAfterDrawing = async () => {
await randomizer.relay(rng.address, 0, ethers.utils.randomBytes(32));
await sortition.passPhase(); // Generating -> Drawing
await core.draw(0, 5000);
await sortition.passPhase(); // Drawing -> Staking
};

describe("When decreasing then increasing back stake", async () => {
before("Setup", async () => {
await deploy();
Expand All @@ -82,9 +90,9 @@ describe("Staking", async () => {
it("Should be outside the Staking phase", async () => {
expect(await sortition.phase()).to.be.equal(1); // Drawing
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(4),
PNK(4000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(2),
PNK(2000),
BigNumber.from(2),
]);
});
Expand All @@ -93,40 +101,58 @@ describe("Staking", async () => {
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(0);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(0);
await expect(core.setStake(2, ONE_THOUSAND_PNK.mul(1)))
await expect(core.setStake(2, PNK(1000)))
.to.emit(core, "StakeDelayedNotTransferred")
.withArgs(deployer, 2, ONE_THOUSAND_PNK.mul(1));
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
.withArgs(deployer, 2, PNK(1000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(4),
PNK(4000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(2),
PNK(2000),
BigNumber.from(2),
]); // stake unchanged, delayed
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore); // No PNK transfer yet
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(1);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([deployer, 2, ONE_THOUSAND_PNK.mul(1), false]);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([deployer, 2, PNK(1000), false]);
});

it("Should delay the stake increase back to the previous amount", async () => {
balanceBefore = await pnk.balanceOf(deployer);
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
await expect(core.setStake(2, ONE_THOUSAND_PNK.mul(2)))
await expect(core.setStake(2, PNK(2000)))
.to.emit(core, "StakeDelayedNotTransferred")
.withArgs(deployer, 2, ONE_THOUSAND_PNK.mul(2));
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(2);
.withArgs(deployer, 2, PNK(2000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(4),
PNK(4000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(2),
PNK(2000),
BigNumber.from(2),
]); // stake unchanged, delayed
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore); // No PNK transfer yet
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(2);
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(2);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 1st delayed stake got deleted
expect(await sortition.delayedStakes(2)).to.be.deep.equal([deployer, 2, ONE_THOUSAND_PNK.mul(2), false]);
expect(await sortition.delayedStakes(2)).to.be.deep.equal([deployer, 2, PNK(2000), false]);
});

it("Should execute the delayed stakes but the stakes should remain the same", async () => {
await reachStakingPhaseAfterDrawing();
balanceBefore = await pnk.balanceOf(deployer);
await expect(sortition.executeDelayedStakes(10)).to.emit(core, "StakeSet").withArgs(deployer, 2, PNK(2000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
PNK(4000),
PNK(300), // we're the only juror so we are drawn 3 times
PNK(2000),
BigNumber.from(2),
]); // stake unchanged, delayed
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore); // No PNK transfer yet
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(2);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(3);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 1st delayed stake got deleted
expect(await sortition.delayedStakes(2)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 2nd delayed stake got deleted
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(0); // no delayed stakes left
});
});

Expand All @@ -139,52 +165,70 @@ describe("Staking", async () => {
it("Should be outside the Staking phase", async () => {
expect(await sortition.phase()).to.be.equal(1); // Drawing
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(4),
PNK(4000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(2),
PNK(2000),
BigNumber.from(2),
]);
});

it("Should transfer PNK but delay the stake increase", async () => {
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(0);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(1));
await pnk.approve(core.address, PNK(1000));
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(0);
await expect(core.setStake(2, ONE_THOUSAND_PNK.mul(3)))
await expect(core.setStake(2, PNK(3000)))
.to.emit(core, "StakeDelayedAlreadyTransferred")
.withArgs(deployer, 2, ONE_THOUSAND_PNK.mul(3));
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
.withArgs(deployer, 2, PNK(3000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(5),
PNK(5000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(3),
PNK(3000),
BigNumber.from(2),
]); // stake has changed immediately, WARNING: this is misleading because it's not actually added to the SortitionSumTree
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore.sub(ONE_THOUSAND_PNK)); // PNK is transferred out of the juror's account
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore.sub(PNK(1000))); // PNK is transferred out of the juror's account
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(1);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([deployer, 2, ONE_THOUSAND_PNK.mul(3), true]);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([deployer, 2, PNK(3000), true]);
});

it("Should cancel out the stake decrease back", async () => {
balanceBefore = await pnk.balanceOf(deployer);
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(1);
await expect(core.setStake(2, ONE_THOUSAND_PNK.mul(2)))
await expect(core.setStake(2, PNK(2000)))
.to.emit(core, "StakeDelayedNotTransferred")
.withArgs(deployer, 2, ONE_THOUSAND_PNK.mul(2));
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(2);
.withArgs(deployer, 2, PNK(2000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
ONE_THOUSAND_PNK.mul(4),
PNK(4000),
BigNumber.from(0),
ONE_THOUSAND_PNK.mul(2),
PNK(2000),
BigNumber.from(2),
]); // stake has changed immediately
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore.add(ONE_THOUSAND_PNK)); // PNK is sent back to the juror
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore.add(PNK(1000))); // PNK is sent back to the juror
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(2);
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(2);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(1);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 1st delayed stake got deleted
expect(await sortition.delayedStakes(2)).to.be.deep.equal([deployer, 2, ONE_THOUSAND_PNK.mul(2), false]);
expect(await sortition.delayedStakes(2)).to.be.deep.equal([deployer, 2, PNK(2000), false]);
});

it("Should execute the delayed stakes but the stakes should remain the same", async () => {
await reachStakingPhaseAfterDrawing();
balanceBefore = await pnk.balanceOf(deployer);
await expect(sortition.executeDelayedStakes(10)).to.emit(core, "StakeSet").withArgs(deployer, 2, PNK(2000));
expect(await core.getJurorBalance(deployer, 2)).to.be.deep.equal([
PNK(4000),
PNK(300), // we're the only juror so we are drawn 3 times
PNK(2000),
BigNumber.from(2),
]); // stake unchanged, delayed
expect(await pnk.balanceOf(deployer)).to.be.equal(balanceBefore); // No PNK transfer yet
expect(await sortition.delayedStakeWriteIndex()).to.be.equal(2);
expect(await sortition.delayedStakeReadIndex()).to.be.equal(3);
expect(await sortition.delayedStakes(1)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 1st delayed stake got deleted
expect(await sortition.delayedStakes(2)).to.be.deep.equal([ethers.constants.AddressZero, 0, 0, false]); // the 2nd delayed stake got deleted
expect(await sortition.latestDelayedStakeIndex(deployer, 2)).to.be.equal(0); // no delayed stakes left
});
});
});
Expand All @@ -195,13 +239,13 @@ describe("Staking", async () => {
});

it("Should unstake from all courts", async () => {
const arbitrationCost = ONE_TENTH_ETH.mul(3);
const arbitrationCost = ETH(0.1).mul(3);

await core.createCourt(1, false, ONE_THOUSAND_PNK, 1000, ONE_TENTH_ETH, 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit
await core.createCourt(1, false, PNK(1000), 1000, ETH(0.1), 3, [0, 0, 0, 0], 3, [1]); // Parent - general court, Classic dispute kit

await pnk.approve(core.address, ONE_THOUSAND_PNK.mul(4));
await core.setStake(1, ONE_THOUSAND_PNK.mul(2));
await core.setStake(2, ONE_THOUSAND_PNK.mul(2));
await pnk.approve(core.address, PNK(4000));
await core.setStake(1, PNK(2000));
await core.setStake(2, PNK(2000));

expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([BigNumber.from("1"), BigNumber.from("2")]);

Expand All @@ -224,7 +268,7 @@ describe("Staking", async () => {
await core.passPeriod(0); // Voting -> Appeal
await core.passPeriod(0); // Appeal -> Execution

await sortition.passPhase(); // Freezing -> Staking. Change so we don't deal with delayed stakes
await sortition.passPhase(); // Drawing -> Staking. Change so we don't deal with delayed stakes

expect(await core.getJurorCourtIDs(deployer)).to.be.deep.equal([BigNumber.from("1"), BigNumber.from("2")]);

Expand Down

0 comments on commit 236d1d3

Please sign in to comment.