Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
SigismundSchlomo committed Oct 7, 2024
1 parent ba3191e commit 0cde971
Show file tree
Hide file tree
Showing 5 changed files with 267 additions and 188 deletions.
5 changes: 0 additions & 5 deletions contracts/staking/token/LimitedTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,4 @@ contract LimitedTokenPool is Initializable, AccessControl, IOnBlockListener {
else info.totalRewardsDebt += newDebt - oldDebt;
stakers[user].rewardsDebt = newDebt;
}

function _isLimitsConfigValid(LimitsConfig calldata config) internal pure returns (bool) {

return true;
}
}
70 changes: 44 additions & 26 deletions test/staking/token/LimitedTokenPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ describe("LimitedTokenPool", function () {
limitsMultiplierToken: limitsMultiplierToken.address,
profitableToken: profitableToken.address,
rewardToken: profitableToken.address,
rewardTokenPrice: 1, // 1:1 ratio
interest: 0.10 * BILLION, // 10%
interestRate: D1, // 1 day
};

const limitsConfig: LimitedTokenPool.LimitsConfigStruct = {
rewardTokenPrice: BILLION, // 1:1 ratio
interest: 0.10 * BILLION, // 10%
interestRate: D1, // 1 day
minDepositValue: 10,
minStakeValue: 10,
fastUnstakePenalty: 0.10 * BILLION, // 10%
Expand Down Expand Up @@ -95,13 +95,13 @@ describe("LimitedTokenPool", function () {
expect(config.limitsMultiplierToken).to.equal(limitsMultiplierToken.address);
expect(config.profitableToken).to.equal(profitableToken.address);
expect(config.rewardToken).to.equal(profitableToken.address);
expect(config.rewardTokenPrice).to.equal(1);
expect(config.interest).to.equal(0.10 * BILLION);
expect(config.interestRate).to.equal(D1);
});

it("Should initialize with correct limits config", async function () {
const limits = await limitedPool.getLimitsConfig();
expect(limits.rewardTokenPrice).to.equal(BILLION);
expect(limits.interest).to.equal(0.10 * BILLION);
expect(limits.interestRate).to.equal(D1);
expect(limits.minDepositValue).to.equal(10);
expect(limits.minStakeValue).to.equal(10);
expect(limits.fastUnstakePenalty).to.equal(0.10 * BILLION);
Expand Down Expand Up @@ -171,9 +171,7 @@ describe("LimitedTokenPool", function () {

it("Should allow staking", async function () {
const stakeAmount = ethers.utils.parseEther("100");
await expect(limitedPool.stake(stakeAmount))
.to.emit(limitedPool, "Staked")
.withArgs(owner.address, stakeAmount);
await limitedPool.stake(stakeAmount);

const info = await limitedPool.getInfo();
expect(info.totalStake).to.equal(stakeAmount);
Expand All @@ -193,7 +191,12 @@ describe("LimitedTokenPool", function () {
});

it("Should not allow staking above total pool limit", async function () {
await limitedPool.setMaxTotalStakeValue(ethers.utils.parseEther("100"));
const limits= await limitedPool.getLimitsConfig();
const updatedLimits = {
...limits,
maxTotalStakeValue: ethers.utils.parseEther("100")
};
await limitedPool.setLimitsConfig(updatedLimits);
const stakeAmount = ethers.utils.parseEther("101");
await expect(limitedPool.stake(stakeAmount)).to.be.revertedWith("Pool: max stake value exceeded");
});
Expand Down Expand Up @@ -224,7 +227,12 @@ describe("LimitedTokenPool", function () {
});

it("Should not allow unstaking before stake lock period", async function () {
await limitedPool.setStakeLockPeriod(D1 * 2);
const limits = await limitedPool.getLimitsConfig();
const updatedLimits = {
...limits,
stakeLockPeriod: ethers.BigNumber.from(D1 * 2)
};
await limitedPool.setLimitsConfig(updatedLimits);
await limitedPool.stake(stakeAmount);
await time.increase(D1 / 2);
await expect(limitedPool.unstake(stakeAmount)).to.be.revertedWith("Stake is locked");
Expand Down Expand Up @@ -285,7 +293,12 @@ describe("LimitedTokenPool", function () {

describe("Edge cases", function () {
it("Should handle multiple deposits and stakes correctly", async function () {
await limitedPool.setStakeLockPeriod(0); // No lock period
const limits = await limitedPool.getLimitsConfig();
const updatedLimits = {
...limits,
stakeLockPeriod: 0,
};
await limitedPool.setLimitsConfig(updatedLimits);
const depositAmount = ethers.utils.parseEther("1000");
const stakeAmount = ethers.utils.parseEther("500");

Expand All @@ -304,7 +317,12 @@ describe("LimitedTokenPool", function () {
});

it("Should handle rewards correctly after multiple stakes and unstakes", async function () {
await limitedPool.setStakeLockPeriod(0); // No lock period
const limits = await limitedPool.getLimitsConfig();
const updatedLimits = {
...limits,
stakeLockPeriod: 0,
};
await limitedPool.setLimitsConfig(updatedLimits);
const depositAmount = ethers.utils.parseEther("2000");
const stakeAmount = ethers.utils.parseEther("500");

Expand Down Expand Up @@ -425,17 +443,19 @@ describe("LimitedTokenPool", function () {
limitsMultiplierToken: limitsMultiplierToken.address,
profitableToken: profitableToken.address,
rewardToken: profitableToken.address,
rewardTokenPrice: BILLION,
interest: 0.10 * BILLION,
interestRate: D1,
};

await expect(limitedPool.initialize(rewardsBank.address, lockKeeper.address, mainConfig))
.to.be.revertedWith("Initializable: contract is already initialized");
});

it("Should only allow admin to change configurations", async function () {
await expect(limitedPool.connect(user1).setRewardTokenPrice(BILLION * 2))
const limits = await limitedPool.getLimitsConfig();
const updatedLimits = {
...limits,
rewardTokenPrice: BILLION * 2
};
await expect(limitedPool.connect(user1).setLimitsConfig(updatedLimits))
.to.be.revertedWith("AccessControl: account " + user1.address.toLowerCase() + " is missing role 0x0000000000000000000000000000000000000000000000000000000000000000");
});

Expand All @@ -454,9 +474,6 @@ describe("LimitedTokenPool", function () {
limitsMultiplierToken: ethers.constants.AddressZero, // ETH
profitableToken: profitableToken.address,
rewardToken: profitableToken.address,
rewardTokenPrice: BILLION,
interest: 0.10 * BILLION,
interestRate: D1,
};

const ethPool = (await upgrades.deployProxy(limitedPoolFactory, [
Expand All @@ -466,6 +483,9 @@ describe("LimitedTokenPool", function () {
])) as LimitedTokenPool;

await ethPool.setLimitsConfig({
rewardTokenPrice: BILLION,
interest: 0.10 * BILLION,
interestRate: D1,
minDepositValue: ethers.utils.parseEther("0.1"),
minStakeValue: ethers.utils.parseEther("0.1"),
fastUnstakePenalty: 0.10 * BILLION,
Expand Down Expand Up @@ -493,9 +513,6 @@ describe("LimitedTokenPool", function () {
limitsMultiplierToken: limitsMultiplierToken.address,
profitableToken: ethers.constants.AddressZero, // ETH
rewardToken: profitableToken.address,
rewardTokenPrice: BILLION,
interest: 0.10 * BILLION,
interestRate: D1,
};

const ethPool = (await upgrades.deployProxy(limitedPoolFactory, [
Expand All @@ -505,6 +522,9 @@ describe("LimitedTokenPool", function () {
])) as LimitedTokenPool;

await ethPool.setLimitsConfig({
rewardTokenPrice: BILLION,
interest: 0.10 * BILLION,
interestRate: D1,
minDepositValue: ethers.utils.parseEther("0.1"),
minStakeValue: ethers.utils.parseEther("0.1"),
fastUnstakePenalty: 0.10 * BILLION,
Expand All @@ -520,9 +540,7 @@ describe("LimitedTokenPool", function () {
await ethPool.deposit(ethers.utils.parseEther("10"));

const stakeAmount = ethers.utils.parseEther("1");
await expect(ethPool.stake(stakeAmount, { value: stakeAmount }))
.to.emit(ethPool, "Staked")
.withArgs(owner.address, stakeAmount);
await ethPool.stake(stakeAmount, { value: stakeAmount });

const info = await ethPool.getInfo();
expect(info.totalStake).to.equal(stakeAmount);
Expand Down
179 changes: 179 additions & 0 deletions test/staking/token/LimitedTokenPoolsManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { ethers, upgrades } from "hardhat";
import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers";

import {
LimitedTokenPoolsManager,
RewardsBank,
AirBond__factory,
LimitedTokenPool,
RewardsBank__factory,
LimitedTokenPoolsManager__factory,
LockKeeper__factory,
LockKeeper,
} from "../../../typechain-types";

import LimitedTokenPoolJson from "../../../artifacts/contracts/staking/token/LimitedTokenPool.sol/LimitedTokenPool.json";

import { expect } from "chai";

describe("LimitedTokenPoolsManager", function () {
let poolsManager: LimitedTokenPoolsManager;
let rewardsBank: RewardsBank;
let tokenAddr: string;
let owner: SignerWithAddress;
let lockKeeper: LockKeeper;

async function deploy() {
const [owner] = await ethers.getSigners();

const rewardsBank = await new RewardsBank__factory(owner).deploy();
const airBond = await new AirBond__factory(owner).deploy(owner.address);

const limitedTokenPoolFactory = await ethers.getContractFactory("LimitedTokenPool");
const limitedTokenPoolBeacon = await upgrades.deployBeacon(limitedTokenPoolFactory);

const lockKeeper = await new LockKeeper__factory(owner).deploy();

const poolsManager = await new LimitedTokenPoolsManager__factory(owner)
.deploy(rewardsBank.address, lockKeeper.address, limitedTokenPoolBeacon.address);

await (await rewardsBank.grantRole(await rewardsBank.DEFAULT_ADMIN_ROLE(), poolsManager.address)).wait();
const tokenAddr = airBond.address;

return { poolsManager, rewardsBank, lockKeeper, tokenAddr, owner };
}

beforeEach(async function () {
({ poolsManager, rewardsBank, lockKeeper, tokenAddr, owner } = await loadFixture(deploy));
});

describe("LimitedTokenPool Management", function () {
it("Should allow the owner to create a limited token pool and set limits", async function () {
const mainConfig: LimitedTokenPool.MainConfigStruct = {
name: "TestPool",
limitsMultiplierToken: tokenAddr,
profitableToken: tokenAddr,
rewardToken: tokenAddr,
};

const tx = await poolsManager.createPool(mainConfig);
const receipt = await tx.wait();
const poolAddress = receipt.events![4].args![0];

expect(await poolsManager.pools(0)).to.equal(poolAddress);

const limitsConfig: LimitedTokenPool.LimitsConfigStruct = {
rewardTokenPrice: ethers.utils.parseUnits("1", 9), // 1 BILLION
interest: ethers.utils.parseUnits("0.1", 9), // 10%
interestRate: 24 * 60 * 60, // 24 hours
minDepositValue: ethers.utils.parseEther("10"),
minStakeValue: ethers.utils.parseEther("10"),
fastUnstakePenalty: ethers.utils.parseUnits("0.1", 9), // 10%
unstakeLockPeriod: 24 * 60 * 60, // 24 hours
stakeLockPeriod: 24 * 60 * 60, // 24 hours
maxTotalStakeValue: ethers.utils.parseEther("1000000"),
maxStakePerUserValue: ethers.utils.parseEther("100000"),
stakeLimitsMultiplier: ethers.utils.parseUnits("2", 9), // 2x
};

await poolsManager.configurePool(poolAddress, limitsConfig);

const proxyPool = new ethers.Contract(poolAddress, LimitedTokenPoolJson.abi, owner);
const updatedConfig = await proxyPool.getLimitsConfig();

expect(updatedConfig.rewardTokenPrice).to.equal(limitsConfig.rewardTokenPrice);
expect(updatedConfig.interest).to.equal(limitsConfig.interest);
expect(updatedConfig.interestRate).to.equal(limitsConfig.interestRate);
expect(updatedConfig.minDepositValue).to.equal(limitsConfig.minDepositValue);
expect(updatedConfig.minStakeValue).to.equal(limitsConfig.minStakeValue);
expect(updatedConfig.fastUnstakePenalty).to.equal(limitsConfig.fastUnstakePenalty);
expect(updatedConfig.unstakeLockPeriod).to.equal(limitsConfig.unstakeLockPeriod);
expect(updatedConfig.stakeLockPeriod).to.equal(limitsConfig.stakeLockPeriod);
expect(updatedConfig.maxTotalStakeValue).to.equal(limitsConfig.maxTotalStakeValue);
expect(updatedConfig.maxStakePerUserValue).to.equal(limitsConfig.maxStakePerUserValue);
expect(updatedConfig.stakeLimitsMultiplier).to.equal(limitsConfig.stakeLimitsMultiplier);
});

it("Should activate and deactivate a limited token pool", async function () {
const mainConfig: LimitedTokenPool.MainConfigStruct = {
name: "TestPool",
limitsMultiplierToken: tokenAddr,
profitableToken: tokenAddr,
rewardToken: tokenAddr,
};

const tx = await poolsManager.createPool(mainConfig);
const receipt = await tx.wait();
console.log(receipt.events);
const poolAddress = receipt.events![4].args![0];

const proxyPool = new ethers.Contract(poolAddress, LimitedTokenPoolJson.abi, owner);
expect(await proxyPool.active()).to.equal(true);
await poolsManager.deactivatePool(poolAddress);
expect(await proxyPool.active()).to.equal(false);
await poolsManager.activatePool(poolAddress);
expect(await proxyPool.active()).to.equal(true);
});

it("Should allow updating limited token pool parameters", async function () {
const mainConfig: LimitedTokenPool.MainConfigStruct = {
name: "TestPool",
limitsMultiplierToken: tokenAddr,
profitableToken: tokenAddr,
rewardToken: tokenAddr,
};

const tx = await poolsManager.createPool(mainConfig);
const receipt = await tx.wait();
const poolAddress = receipt.events![4].args![0];

const initialLimitsConfig: LimitedTokenPool.LimitsConfigStruct = {
rewardTokenPrice: ethers.utils.parseUnits("1", 9),
interest: ethers.utils.parseUnits("0.1", 9),
interestRate: 24 * 60 * 60,
minDepositValue: ethers.utils.parseEther("10"),
minStakeValue: ethers.utils.parseEther("10"),
fastUnstakePenalty: ethers.utils.parseUnits("0.1", 9),
unstakeLockPeriod: 24 * 60 * 60,
stakeLockPeriod: 24 * 60 * 60,
maxTotalStakeValue: ethers.utils.parseEther("1000000"),
maxStakePerUserValue: ethers.utils.parseEther("100000"),
stakeLimitsMultiplier: ethers.utils.parseUnits("2", 9),
};

await poolsManager.configurePool(poolAddress, initialLimitsConfig);

const proxyPool = new ethers.Contract(poolAddress, LimitedTokenPoolJson.abi, owner);

const newLimitsConfig: LimitedTokenPool.LimitsConfigStruct = {
rewardTokenPrice: ethers.utils.parseUnits("2", 9),
interest: ethers.utils.parseUnits("0.2", 9),
interestRate: 48 * 60 * 60,
minDepositValue: ethers.utils.parseEther("20"),
minStakeValue: ethers.utils.parseEther("20"),
fastUnstakePenalty: ethers.utils.parseUnits("0.2", 9),
unstakeLockPeriod: 48 * 60 * 60,
stakeLockPeriod: 48 * 60 * 60,
maxTotalStakeValue: ethers.utils.parseEther("2000000"),
maxStakePerUserValue: ethers.utils.parseEther("200000"),
stakeLimitsMultiplier: ethers.utils.parseUnits("3", 9),
};

await poolsManager.configurePool(poolAddress, newLimitsConfig);
const updatedConfig = await proxyPool.getLimitsConfig();

expect(updatedConfig.rewardTokenPrice).to.equal(newLimitsConfig.rewardTokenPrice);
expect(updatedConfig.interest).to.equal(newLimitsConfig.interest);
expect(updatedConfig.interestRate).to.equal(newLimitsConfig.interestRate);
expect(updatedConfig.minDepositValue).to.equal(newLimitsConfig.minDepositValue);
expect(updatedConfig.minStakeValue).to.equal(newLimitsConfig.minStakeValue);
expect(updatedConfig.fastUnstakePenalty).to.equal(newLimitsConfig.fastUnstakePenalty);
expect(updatedConfig.unstakeLockPeriod).to.equal(newLimitsConfig.unstakeLockPeriod);
expect(updatedConfig.stakeLockPeriod).to.equal(newLimitsConfig.stakeLockPeriod);
expect(updatedConfig.maxTotalStakeValue).to.equal(newLimitsConfig.maxTotalStakeValue);
expect(updatedConfig.maxStakePerUserValue).to.equal(newLimitsConfig.maxStakePerUserValue);
expect(updatedConfig.stakeLimitsMultiplier).to.equal(newLimitsConfig.stakeLimitsMultiplier);
});
});
});
11 changes: 7 additions & 4 deletions test/staking/token/TokenPool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const D1 = 24 * 60 * 60;
const BILLION = 1000000000;

import { expect } from "chai";
describe("SingleSidePool", function () {
describe("TokenPool", function () {
let owner: SignerWithAddress;
let tokenPool: TokenPool;
let rewardsBank: RewardsBank;
Expand All @@ -31,19 +31,22 @@ describe("SingleSidePool", function () {

const tokenPoolFactory = await ethers.getContractFactory("TokenPool");

const tokenPoolParams: TokenPool.ConfigStruct = {
const mainConfig: TokenPool.MainConfigStruct = {
token: token.address,
name: "Test",
rewardToken: token.address,
};

const limitsConfig: TokenPool.LimitsConfigStruct = {
minStakeValue: 10,
fastUnstakePenalty: 0.10 * BILLION, // 10%
interest: 0.10 * BILLION, // 10%
interestRate: D1, // 1 day
lockPeriod: D1, // 1 day
rewardToken: token.address,
rewardTokenPrice: 1,
};

const tokenPool = (await upgrades.deployProxy(tokenPoolFactory, [rewardsBank.address, lockKeeper.address, tokenPoolParams])) as TokenPool;
const tokenPool = (await upgrades.deployProxy(tokenPoolFactory, [rewardsBank.address, lockKeeper.address, mainConfig, limitsConfig])) as TokenPool;

await (await rewardsBank.grantRole(await rewardsBank.DEFAULT_ADMIN_ROLE(), tokenPool.address)).wait();
await (await token.grantRole(await token.MINTER_ROLE(), owner.address)).wait();
Expand Down
Loading

0 comments on commit 0cde971

Please sign in to comment.