@gooddollar/goodprotocol
Version:
GoodDollar Protocol
725 lines (645 loc) • 28.3 kB
text/typescript
import { default as hre, ethers, upgrades } from "hardhat";
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { GoodMarketMaker, CERC20 } from "../../types";
import { createDAO, increaseTime } from "../helpers";
const BN = ethers.BigNumber;
export const NULL_ADDRESS = ethers.constants.AddressZero;
let cdai: CERC20;
describe("GoodMarketMaker - calculate gd value at reserve", () => {
let goodDollar,
controller,
avatar,
formula,
marketMaker: GoodMarketMaker,
dai,
cdai,
founder,
staker,
signers,
initializeToken,
fakeReserve;
const deployDAIMock = async () => {
let dai = await (await ethers.getContractFactory("DAIMock")).deploy();
return dai.address;
};
const deploycDAIMock = async () => {
let cdai = await (await ethers.getContractFactory("cDAIMock")).deploy(dai);
return cdai.address;
};
before(async () => {
[founder, staker, fakeReserve, ...signers] = await ethers.getSigners();
let {
controller: ctrl,
avatar: av,
gd: goodDollar,
identity,
daoCreator,
nameService,
marketMaker: mm,
setSchemes,
setReserveToken,
setDAOAddress
} = await loadFixture(createDAO);
avatar = av;
marketMaker = mm.connect(fakeReserve);
controller = ctrl;
initializeToken = setReserveToken;
console.log("deployed dao", { goodDollar, identity, controller, avatar });
dai = await deployDAIMock();
cdai = await deploycDAIMock();
//give founder generic call permission
await setSchemes([founder.address]);
await setDAOAddress("RESERVE", fakeReserve.address);
console.log("starting tests...");
});
it("should initialize a token with 0 ratio and the ratio should calculate as 100% by default", async () => {
let dai = await deployDAIMock();
await initializeToken(
dai,
"100",
"10000",
"0" //0% rr
);
let newreserveratio = await marketMaker.calculateNewReserveRatio(dai);
expect(newreserveratio.toString()).to.be.equal("1000000"); // no need to expand at day 0
await increaseTime(24 * 60 * 60);
newreserveratio = await marketMaker.calculateNewReserveRatio(dai);
expect(newreserveratio.toString()).to.be.equal("999388", "first expansion"); // result of initial expansion rate * 100% ratio
await increaseTime(24 * 60 * 60 * 0.5); //expansion should happen at full day intervals
newreserveratio = await marketMaker.calculateNewReserveRatio(dai);
expect(newreserveratio.toString()).to.be.equal("999388", "day and half");
await increaseTime(24 * 60 * 60 * 0.5); //expansion should happen at full day intervals
newreserveratio = await marketMaker.calculateNewReserveRatio(dai);
expect(newreserveratio.toString()).to.be.equal(
"998778",
"second expansion"
);
});
it("should update token reserve ratio after first 24 hours", async () => {
let dai1 = await deployDAIMock();
await initializeToken(
dai1,
"100",
"10000",
"0" //0% rr
);
await increaseTime(24 * 60 * 60);
await marketMaker.expandReserveRatio(dai1);
const rr = await marketMaker.reserveTokens(dai1);
expect(rr["1"].toString()).to.be.equal("999388"); // result of initial expansion rate * 100% ratio
});
it("should initialize token with price", async () => {
const expansion = await initializeToken(
cdai,
"100", //1gd
"10000", //0.0001 cDai
"1000000" //100% rr
);
const price = await marketMaker.currentPrice(cdai);
expect(price.toString()).to.be.equal("10000"); //1gd is equal 0.0001 cDAI = 100000 wei;
const onecDAIReturn = await marketMaker.buyReturn(
cdai,
"100000000" //1cDai
);
expect(onecDAIReturn.toNumber() / 100).to.be.equal(10000); //0.0001 cdai is 1 gd, so for 1eth you get 10000 gd (divide by 100 to account for 2 decimals precision)
});
it("should calculate mint UBI correctly for 8 decimals precision when price is 0.0001 and 100% ratio", async () => {
const expansion = await initializeToken(
cdai,
"100", //1gd
"10000", //0.0001 cDai
"1000000" //100% rr
);
const gdPrice = await marketMaker.currentPrice(cdai);
const toMint = await marketMaker.calculateMintInterest(cdai, "100000000");
const expectedTotalMinted = 10 ** 8 / gdPrice.toNumber(); //1cdai divided by gd price;
expect(expectedTotalMinted).to.be.equal(10000); //1k GD since price is 0.0001 cdai for 1 gd
expect(toMint.toString()).to.be.equal(
(expectedTotalMinted * 100).toString()
); //add 2 decimals precision
});
it("should update reserve ratio by days passed", async () => {
const expansion = await marketMaker.reserveRatioDailyExpansion();
// 20% yearly. set up in the constructor
expect(expansion.toString()).to.be.equal("999388834642296000000000000");
await increaseTime(24 * 60 * 60);
await marketMaker.expandReserveRatio(cdai);
const daytwoRR = await marketMaker.reserveTokens(cdai);
// after interval expansion
expect(daytwoRR["1"].toString()).to.be.equal("999388");
await increaseTime(24 * 60 * 60);
await marketMaker.expandReserveRatio(cdai);
const daythreeRR = await marketMaker.reserveTokens(cdai);
// after interval expansion
expect(daythreeRR["1"].toString()).to.be.equal("998777");
await increaseTime(24 * 60 * 60 * 7);
//after extra 7 days.
await marketMaker.expandReserveRatio(cdai);
expect(
await marketMaker
.reserveTokens(cdai)
.then(_ => _["reserveRatio"].toString())
).to.be.equal("994511"); // 998777 * 0.999388834642296000000000000^7
});
it("should not return a sell contribution if the given gd is less than the given contribution amount", async () => {
let dai = await deployDAIMock();
const MM = await ethers.getContractFactory("GoodMarketMaker", fakeReserve);
const marketMaker1 = await upgrades.deployProxy(MM, [
await marketMaker.nameService(),
999388834642296,
1e15
]);
await marketMaker1.initializeToken(
dai,
"100", //1gd
ethers.utils.parseEther("0.0001"),
"800000", //80% rr,
0
);
const res = marketMaker1.sellWithContribution(
dai,
ethers.utils.parseEther("1"),
ethers.utils.parseEther("2")
);
await expect(res).to.be.revertedWith(
/GD amount is lower than the contribution amount/
);
});
it("should be able to calculate and update bonding curve gd balance based on oncoming cDAI and the price stays the same", async () => {
let priceBefore = await marketMaker.currentPrice(cdai);
await marketMaker.mintInterest(cdai, BN.from(1e8));
let priceAfter = await marketMaker.currentPrice(cdai);
expect(priceAfter).gt(0);
expect(priceBefore).gt(0);
expect(Math.floor(priceAfter.toNumber() / 100).toString()).to.be.equal(
Math.floor(priceBefore.toNumber() / 100).toString()
);
// very large amount of cdai
priceBefore = await marketMaker.currentPrice(cdai);
await marketMaker.mintInterest(cdai, ethers.utils.parseEther("1"));
priceAfter = await marketMaker.currentPrice(cdai);
console.log({ priceAfter, priceBefore });
expect(priceAfter).gt(0);
expect(priceBefore).gt(0);
expect(priceAfter).to.eq(priceBefore);
});
it("should not be able to mint interest by a non owner", async () => {
let res = marketMaker.connect(staker).mintInterest(cdai, BN.from(1e8));
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should not be able to mint expansion by a non owner", async () => {
let res = marketMaker.connect(staker).mintExpansion(cdai);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should mint 0 gd tokens if the add token supply is 0", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
await marketMaker.mintInterest(cdai, "0");
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
expect(gdSupplyAfter.toString()).to.be.equal(gdSupplyBefore.toString());
});
it("should be able to update the reserve ratio only by the owner", async () => {
let res = marketMaker.connect(staker).expandReserveRatio(cdai);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should be able to mint interest only by the owner", async () => {
let res = marketMaker.connect(staker).mintInterest(cdai, BN.from(1e8));
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should be able to mint expansion only by the owner", async () => {
let res = marketMaker.connect(staker).mintExpansion(cdai);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should be able to calculate minted gd based on expansion of reserve ratio, the price stays the same", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let reserveRatioBefore = reserveTokenBefore.reserveRatio;
await increaseTime(24 * 60 * 60);
const priceBefore = await marketMaker.currentPrice(cdai);
const toMint = await marketMaker.calculateMintExpansion(cdai);
expect(toMint.toString()).not.to.be.equal("0");
const newRR = await marketMaker.calculateNewReserveRatio(cdai);
expect(reserveRatioBefore.toString()).not.to.be.equal(newRR.toString());
const priceAfter = await marketMaker.currentPrice(cdai);
expect(priceAfter.toString()).to.be.equal(priceBefore.toString());
});
it("should be able to calculate and update gd supply based on expansion of reserve ratio, the price stays the same", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
let reserveRatioBefore = reserveTokenBefore.reserveRatio;
const priceBefore = await marketMaker.currentPrice(cdai);
await marketMaker.mintExpansion(cdai);
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
let reserveRatioAfter = reserveTokenAfter.reserveRatio;
const priceAfter = await marketMaker.currentPrice(cdai);
expect(priceAfter.toString()).to.be.equal(priceBefore.toString());
expect(gdSupplyBefore.toString()).not.to.be.equal(gdSupplyAfter.toString());
expect(reserveRatioBefore.toString()).not.to.be.equal(
reserveRatioAfter.toString()
);
});
it("should have new return amount when RR is not 100%", async () => {
const expansion = await initializeToken(
dai,
"100", //1gd
ethers.utils.parseEther("0.0001"), //0.0001 dai
"800000" //80% rr
);
const price = await marketMaker.currentPrice(dai);
expect(price.toString()).to.be.equal(ethers.utils.parseEther("0.000125")); //1gd is equal 0.0001/1*0.8 = 0.000125
const oneDAIReturn = await marketMaker.buyReturn(
dai,
ethers.utils.parseEther("1") //1Dai
);
//bancor formula to calcualte return
//gd return = gdsupply * ((1+tokenamount/tokensupply)^rr -1)
const expectedReturn = 1 * ((1 + 1 / 0.0001) ** 0.8 - 1);
expect(oneDAIReturn.toNumber() / 100).to.be.equal(
Math.floor(expectedReturn * 100) / 100
);
});
it("should calculate mint UBI correctly for 18 decimals precision", async () => {
const gdPrice = await marketMaker.currentPrice(dai);
const toMint = await marketMaker.calculateMintInterest(
dai,
ethers.utils.parseEther("1")
);
let reserveToken = await marketMaker.reserveTokens(dai);
//we expect price to stay the same p = reserve/supply*RR
const newPrice = reserveToken.reserveSupply
.add(ethers.utils.parseEther("1"))
.mul(1e8)
.div(reserveToken.gdSupply.add(toMint).mul(reserveToken.reserveRatio));
expect(newPrice).equal(gdPrice);
// the formula is amountToMint = reserveInterest * tokenSupply / reserveBalance
const expectedTotalMinted =
(10 ** 18 * reserveToken.gdSupply.toNumber()) /
reserveToken.reserveSupply.toNumber();
expect(expectedTotalMinted).to.be.equal(1000000);
expect(toMint.toString()).to.be.equal(expectedTotalMinted.toString());
});
it("should calculate sell return with cDAI", async () => {
await initializeToken(
cdai,
"1000000000", //1gd
"100000000000", //0.0001 cDai
"900000" //80% rr
);
const gDReturn = await marketMaker.sellReturn(
cdai,
10 //0.1 gd
);
let reserveToken = await marketMaker.reserveTokens(cdai);
let reserveBalance = reserveToken.reserveSupply.toNumber();
let sellAmount = 10;
let supply = reserveToken.gdSupply.toNumber();
let rr = reserveToken.reserveRatio;
// sell formula (as in calculateSaleReturn):
// return = reserveBalance * (1 - (1 - sellAmount / supply) ^ (1000000 / reserveRatio))
const expectedReturn =
reserveBalance * (1 - (1 - sellAmount / supply) ** (1000000 / rr));
expect(gDReturn.toNumber()).to.be.equal(Math.floor(expectedReturn));
});
it("should calculate sell return with DAI", async () => {
const gDReturn = await marketMaker.sellReturn(
dai,
10 //0.1 gd
);
let reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalance = reserveToken.reserveSupply.toNumber();
let sellAmount = 10;
let supply = reserveToken.gdSupply.toNumber();
let rr = reserveToken.reserveRatio;
// sell formula (as in calculateSaleReturn):
// return = reserveBalance * (1 - (1 - sellAmount / supply) ^ (1000000 / reserveRatio))
const expectedReturn =
reserveBalance * (1 - (1 - sellAmount / supply) ** (1000000 / rr));
expect(gDReturn.toNumber()).to.be.equal(Math.floor(expectedReturn));
});
it("should be able to update balances based on buy return calculation", async () => {
let reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceBefore = reserveToken.reserveSupply;
let supplyBefore = reserveToken.gdSupply;
let rrBefore = reserveToken.reserveRatio;
let amount = ethers.utils.parseEther("1");
let transaction = await (
await marketMaker.buy(
dai,
ethers.utils.parseEther("1") //1Dai
)
).wait();
reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceAfter = reserveToken.reserveSupply;
let supplyAfter = reserveToken.gdSupply;
let rrAfter = reserveToken.reserveRatio;
expect(transaction.events[0].event).to.be.equal("BalancesUpdated");
expect(reserveBalanceAfter.sub(reserveBalanceBefore)).to.be.equal(
BN.from(amount)
);
expect(supplyAfter.sub(supplyBefore)).to.be.equal(
transaction.events[0].args.returnAmount
);
expect(rrAfter.toString()).to.be.equal(rrBefore.toString());
});
it("should be able to update balances based on sell return calculation", async () => {
let reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceBefore = reserveToken.reserveSupply;
let supplyBefore = reserveToken.gdSupply;
let rrBefore = reserveToken.reserveRatio;
let amount = 100;
let transaction = await (
await marketMaker.sellWithContribution(dai, 100, 0)
).wait();
reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceAfter = reserveToken.reserveSupply;
let supplyAfter = reserveToken.gdSupply;
let rrAfter = reserveToken.reserveRatio;
expect(transaction.events[0].event).to.be.equal("BalancesUpdated");
expect(
reserveBalanceAfter
.add(transaction.events[0].args.returnAmount)
.toString()
).to.be.equal(reserveBalanceBefore.toString());
expect(supplyBefore.sub(supplyAfter)).to.be.equal(BN.from(amount));
expect(rrAfter.toString()).to.be.equal(rrBefore.toString());
});
it("should be able to update balances based on sell with contribution return calculation", async () => {
let reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceBefore = reserveToken.reserveSupply;
let supplyBefore = reserveToken.gdSupply;
let rrBefore = reserveToken.reserveRatio;
let amount = 100;
let transaction = await (
await marketMaker.sellWithContribution(dai, 100, 80)
).wait();
reserveToken = await marketMaker.reserveTokens(dai);
let reserveBalanceAfter = reserveToken.reserveSupply;
let supplyAfter = reserveToken.gdSupply;
let rrAfter = reserveToken.reserveRatio;
expect(transaction.events[0].event).to.be.equal("BalancesUpdated");
expect(
reserveBalanceAfter
.add(transaction.events[0].args.returnAmount)
.toString()
).to.be.equal(reserveBalanceBefore.toString());
expect(supplyBefore.sub(supplyAfter)).to.be.equal(BN.from(amount));
expect(rrAfter).gte(rrBefore); //with sell contribution G$ are burned and increase RR
});
it("should not be able to calculate the buy return in gd and update the bonding curve params by a non-owner account", async () => {
let res = marketMaker
.connect(staker)
.buy(dai, ethers.utils.parseEther("1"));
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should not be able to calculate the sell return in reserve token and update the bonding curve params by a non-owner account", async () => {
let res = marketMaker.connect(staker).sellWithContribution(dai, 100, 0);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should not be able to calculate the sellWithContribution return in reserve token and update the bonding curve params by a non-owner account", async () => {
let res = marketMaker.connect(staker).sellWithContribution(dai, 100, 80);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should be able to buy only with active token", async () => {
let reserveToken = await marketMaker.reserveTokens(cdai);
let gdSupplyBefore = reserveToken.gdSupply;
let reserveSupplyBefore = reserveToken.reserveSupply;
let reserveRatioBefore = reserveToken.reserveRatio;
await initializeToken(
cdai,
"0",
reserveSupplyBefore.toString(),
reserveRatioBefore.toString()
);
let res = marketMaker.buy(cdai, ethers.utils.parseEther("1"));
await expect(res).to.be.revertedWith(/Reserve token not initialized/);
await initializeToken(
cdai,
gdSupplyBefore,
reserveSupplyBefore.toString(),
reserveRatioBefore.toString()
);
});
it("should be able to sell only with active token", async () => {
let res = marketMaker.sellWithContribution(
NULL_ADDRESS,
ethers.utils.parseEther("1"),
0
);
await expect(res).to.be.revertedWith(/Reserve token not initialized/);
});
it("should be able to sellWithContribution only with active token", async () => {
let res = marketMaker.sellWithContribution(
NULL_ADDRESS,
ethers.utils.parseEther("1"),
ethers.utils.parseEther("1")
);
await expect(res).to.be.revertedWith(/Reserve token not initialized/);
});
it("should be able to sell gd only when the amount is lower than the total supply", async () => {
let reserveToken = await marketMaker.reserveTokens(cdai);
let gdSupply = reserveToken.gdSupply;
let res = marketMaker.sellWithContribution(
cdai,
gdSupply.add(BN.from(1)),
0
);
await expect(res).to.be.revertedWith(
/GD amount is higher than the total supply/
);
});
it("should set reserve ratio daily expansion by owner", async () => {
let denom = BN.from(1e15);
const MM = await ethers.getContractFactory("GoodMarketMaker");
const ctrl = await ethers.getContractAt("Controller", controller, founder);
let currentReserveRatioDailyExpansion =
await marketMaker.reserveRatioDailyExpansion();
await marketMaker.setReserveRatioDailyExpansion(1, 1e15);
let newReserveRatioDailyExpansion =
await marketMaker.reserveRatioDailyExpansion();
expect(newReserveRatioDailyExpansion).to.be.equal(BN.from("1000000000000"));
await marketMaker.setReserveRatioDailyExpansion(999388834642296, 1e15);
let reserveRatioDailyExpansion =
await marketMaker.reserveRatioDailyExpansion();
expect(reserveRatioDailyExpansion).to.be.equal(
BN.from("999388834642296000000000000")
);
});
it("should be able to set the reserve ratio daily expansion only by the owner", async () => {
let res = marketMaker
.connect(staker)
.setReserveRatioDailyExpansion(1, 1e15);
await expect(res).to.be.revertedWith(
/GoodMarketMaker: not Reserve or Avatar/
);
});
it("should calculate amount of gd to mint based on incoming cDAI without effecting bonding curve price", async () => {
await initializeToken(dai, 6e11, ethers.utils.parseEther("600000"), 5e5);
const priceBefore = await marketMaker.currentPrice(dai);
await marketMaker.mintInterest(dai, ethers.utils.parseEther("100"));
const priceAfter = await marketMaker.currentPrice(dai);
expect(priceBefore.toString()).to.be.equal(priceAfter.toString());
});
it("should calculate amount of gd to mint based on incoming cDAI with small precision issue effecting bonding curve price in very low amounts", async () => {
await initializeToken(dai, 600, 600000000, 5e5);
const priceBefore = await marketMaker.currentPrice(dai);
await marketMaker.mintInterest(dai, 60000);
const priceAfter = await marketMaker.currentPrice(dai);
expect(priceBefore).equal(200000000);
expect(priceAfter).equal(200020000);
});
it("should not change the reserve ratio when calculate how much decrease it for the reservetoken", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let reserveRatioBefore = reserveTokenBefore.reserveRatio;
await marketMaker.calculateNewReserveRatio(cdai);
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let reserveRatioAfter = reserveTokenAfter.reserveRatio;
expect(reserveRatioBefore.toString()).to.be.equal(
reserveRatioAfter.toString()
);
});
it("should not change the gd supply when calculate how much gd to mint based on added token supply from interest", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
await marketMaker.calculateMintInterest(cdai, "100000000");
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
expect(gdSupplyAfter.toString()).to.be.equal(gdSupplyBefore.toString());
});
it("should not change the gd supply when calculate how much gd to mint based on expansion change", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
await marketMaker.calculateMintExpansion(cdai);
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
expect(gdSupplyAfter.toString()).to.be.equal(gdSupplyBefore.toString());
});
it("should price decrease after sell gd when RR is not 100%", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdPriceBefore = await marketMaker.currentPrice(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
let reserveRatioBefore = reserveTokenBefore.reserveRatio;
let reserveSupplyBefore = reserveTokenBefore.reserveSupply;
await marketMaker.sellWithContribution(cdai, BN.from("500000"), 0);
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
let reserveRatioAfter = reserveTokenAfter.reserveRatio;
let gdPriceAfter = await marketMaker.currentPrice(cdai);
let reserveSupplyAfter = reserveTokenAfter.reserveSupply;
expect(gdPriceAfter.lt(gdPriceBefore));
expect(reserveRatioAfter).to.be.equal(reserveRatioBefore);
});
it("should price increase after buy gd when RR is not %100", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
let gdPriceBefore = await marketMaker.currentPrice(cdai);
let gdSupplyBefore = reserveTokenBefore.gdSupply;
let reserveRatioBefore = reserveTokenBefore.reserveRatio;
let reserveSupplyBefore = reserveTokenBefore.reserveSupply;
await marketMaker.buy(cdai, BN.from("500000"));
let reserveTokenAfter = await marketMaker.reserveTokens(cdai);
let gdSupplyAfter = reserveTokenAfter.gdSupply;
let reserveRatioAfter = reserveTokenAfter.reserveRatio;
let gdPriceAfter = await marketMaker.currentPrice(cdai);
let reserveSupplyAfter = reserveTokenAfter.reserveSupply;
expect(gdPriceAfter.gt(gdPriceBefore));
expect(reserveRatioAfter).to.be.equal(reserveRatioBefore);
});
it("should not set reserve ratio daily expansion with illigal values", async () => {
const invalidZeroDenominator = 0;
await expect(
marketMaker.setReserveRatioDailyExpansion(1, invalidZeroDenominator)
).to.be.revertedWith(/denominator must be above 0/);
const denominator = 1;
const nominatorHigherThanDenom = 2;
await expect(
marketMaker.setReserveRatioDailyExpansion(
nominatorHigherThanDenom,
denominator
)
).to.be.revertedWith(/Invalid nom or denom value/);
});
it("should return same amount when splitting sell into two when exit fee is 0", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
console.log({ reserveTokenBefore });
const res = await (
await marketMaker.sellWithContribution(cdai, "100000000", "0")
).wait();
let reserveTokenAfterSale = await marketMaker.reserveTokens(cdai);
console.log({ reserveTokenAfterSale });
await marketMaker.initializeToken(
cdai,
reserveTokenBefore.gdSupply,
reserveTokenBefore.reserveSupply,
reserveTokenBefore.reserveRatio,
0
);
const split1 = await (
await marketMaker.sellWithContribution(cdai, "50000000", "0")
).wait();
const split2 = await (
await marketMaker.sellWithContribution(cdai, "50000000", "0")
).wait();
let reserveTokenAfterSplitSale = await marketMaker.reserveTokens(cdai);
expect(reserveTokenAfterSale.gdSupply).eq(
reserveTokenAfterSplitSale.gdSupply
);
expect(reserveTokenAfterSale.reserveSupply).eq(
reserveTokenAfterSplitSale.reserveSupply
);
});
it("should have minimal effect on return value when splitting sell into two txs when exit fee is non 0", async () => {
let reserveTokenBefore = await marketMaker.reserveTokens(cdai);
await marketMaker.initializeToken(
cdai,
reserveTokenBefore.gdSupply,
reserveTokenBefore.reserveSupply,
200000,
0
);
console.log({ reserveTokenBefore });
const res = await (
await marketMaker.sellWithContribution(cdai, "500000000", "50000000")
).wait();
let reserveTokenAfterSale = await marketMaker.reserveTokens(cdai);
console.log({ reserveTokenAfterSale });
await marketMaker.initializeToken(
cdai,
reserveTokenBefore.gdSupply,
reserveTokenBefore.reserveSupply,
200000,
0
);
const split1 = await (
await marketMaker.sellWithContribution(cdai, "250000000", "25000000")
).wait();
const split2 = await (
await marketMaker.sellWithContribution(cdai, "250000000", "25000000")
).wait();
let reserveTokenAfterSplitSale = await marketMaker.reserveTokens(cdai);
console.log({ reserveTokenAfterSplitSale });
expect(reserveTokenAfterSale.gdSupply).eq(
reserveTokenAfterSplitSale.gdSupply
);
expect(
Number(reserveTokenAfterSplitSale.reserveSupply) /
Number(reserveTokenAfterSale.reserveSupply)
).gte(0.981);
});
});