fix test
This commit is contained in:
@@ -70,11 +70,11 @@ describe("Funding", () => {
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(ctx.CP.options.address).call(), "2997000000000000000000")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), "0")
|
||||
|
||||
await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder1))
|
||||
await ctx.CP.methods.bidderClaim(bidder1, "0x").send(ctx.sendParam(bidder1))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(bidder1).call(), "999000000000000000000")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), "0")
|
||||
|
||||
await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder2))
|
||||
await ctx.CP.methods.bidderClaim(bidder2, "0x").send(ctx.sendParam(bidder2))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(bidder2).call(), "1998000000000000000000")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), "0")
|
||||
|
||||
@@ -93,11 +93,11 @@ describe("Funding", () => {
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(ctx.CP.options.address).call(), "5000000000000000000000")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), decimalStr("39910"))
|
||||
|
||||
await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder1))
|
||||
await ctx.CP.methods.bidderClaim(bidder1, "0x").send(ctx.sendParam(bidder1))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(bidder1).call(), "1666666666666666666666")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), "13303333333333333333333")
|
||||
|
||||
await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder2))
|
||||
await ctx.CP.methods.bidderClaim(bidder2, "0x").send(ctx.sendParam(bidder2))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(bidder2).call(), "3333333333333333333333")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), "26606666666666666666666")
|
||||
})
|
||||
|
||||
@@ -1,633 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr } from './utils/Converter';
|
||||
|
||||
let lp1: string;
|
||||
let lp2: string;
|
||||
let trader: string;
|
||||
let tempAccount: string;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
tempAccount = ctx.spareAccounts[5];
|
||||
lp1 = ctx.spareAccounts[0];
|
||||
lp2 = ctx.spareAccounts[1];
|
||||
trader = ctx.spareAccounts[2];
|
||||
await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.approveDODO(lp1);
|
||||
await ctx.approveDODO(lp2);
|
||||
await ctx.approveDODO(trader);
|
||||
}
|
||||
|
||||
describe("Admin", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("Settings", () => {
|
||||
it("set oracle", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setOracle(tempAccount)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._ORACLE_().call(), tempAccount);
|
||||
});
|
||||
|
||||
it("set suprevisor", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setSupervisor(tempAccount)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._SUPERVISOR_().call(), tempAccount);
|
||||
});
|
||||
|
||||
it("set maintainer", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setMaintainer(tempAccount)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._MAINTAINER_().call(), tempAccount);
|
||||
});
|
||||
|
||||
it("set liquidity provider fee rate", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setLiquidityProviderFeeRate(decimalStr("0.01"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._LP_FEE_RATE_().call(),
|
||||
decimalStr("0.01")
|
||||
);
|
||||
});
|
||||
|
||||
it("set maintainer fee rate", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setMaintainerFeeRate(decimalStr("0.01"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._MT_FEE_RATE_().call(),
|
||||
decimalStr("0.01")
|
||||
);
|
||||
});
|
||||
|
||||
it("set k", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setK(decimalStr("0.2"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._K_().call(), decimalStr("0.2"));
|
||||
});
|
||||
|
||||
it("set gas price limit", async () => {
|
||||
await ctx.DODO.methods
|
||||
.setGasPriceLimit(decimalStr("100"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._GAS_PRICE_LIMIT_().call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Controls", () => {
|
||||
it("control flow", async () => {
|
||||
await ctx.DODO.methods
|
||||
.disableBaseDeposit()
|
||||
.send(ctx.sendParam(ctx.Supervisor));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)),
|
||||
/DEPOSIT_BASE_NOT_ALLOWED/
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.enableBaseDeposit()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.disableQuoteDeposit()
|
||||
.send(ctx.sendParam(ctx.Supervisor));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/DEPOSIT_QUOTE_NOT_ALLOWED/
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.enableQuoteDeposit()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.disableTrading()
|
||||
.send(ctx.sendParam(ctx.Supervisor));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/TRADE_NOT_ALLOWED/
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("101")
|
||||
);
|
||||
});
|
||||
|
||||
it("control flow premission", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.setGasPriceLimit("1").send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.disableTrading().send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.disableQuoteDeposit().send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.disableBaseDeposit().send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.disableBuying().send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.disableSelling().send(ctx.sendParam(trader)),
|
||||
/NOT_SUPERVISOR_OR_OWNER/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.setOracle(trader).send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.setSupervisor(trader).send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.setMaintainer(trader).send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setLiquidityProviderFeeRate(decimalStr("0.1"))
|
||||
.send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setMaintainerFeeRate(decimalStr("0.1"))
|
||||
.send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.setK(decimalStr("0.1")).send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableTrading().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableBuying().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableSelling().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setBaseBalanceLimit(decimalStr("0"))
|
||||
.send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setQuoteBalanceLimit(decimalStr("0"))
|
||||
.send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableTrading().send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
});
|
||||
|
||||
it("advanced controls", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.disableBuying()
|
||||
.send(ctx.sendParam(ctx.Supervisor));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/BUYING_NOT_ALLOWED/
|
||||
);
|
||||
await ctx.DODO.methods.enableBuying().send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.disableSelling()
|
||||
.send(ctx.sendParam(ctx.Supervisor));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("1"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/SELLING_NOT_ALLOWED/
|
||||
);
|
||||
await ctx.DODO.methods.enableSelling().send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.setBaseBalanceLimit(decimalStr("0"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.depositBase(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/BASE_BALANCE_LIMIT_EXCEEDED/
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.setQuoteBalanceLimit(decimalStr("0"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/QUOTE_BALANCE_LIMIT_EXCEEDED/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Final settlement", () => {
|
||||
it("final settlement when R is ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("10000")
|
||||
);
|
||||
});
|
||||
|
||||
it("final settlement when R is ABOVE ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("94.995")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
"10551951805416248746110"
|
||||
);
|
||||
});
|
||||
|
||||
it("final settlement when R is BELOW ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("100"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("105")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
"9540265973590798352835"
|
||||
);
|
||||
});
|
||||
|
||||
it("final settlement when only deposit base", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
});
|
||||
|
||||
it("final settlement when only deposit quote", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1));
|
||||
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("10000")
|
||||
);
|
||||
});
|
||||
|
||||
it("final settlement revert cases", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)),
|
||||
/DODO_NOT_CLOSED/
|
||||
);
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("500"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.finalSettlement()
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.finalSettlement().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)),
|
||||
/DODO_CLOSED/
|
||||
)
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)),
|
||||
/DODO_CLOSED/
|
||||
)
|
||||
|
||||
await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp2));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp2)),
|
||||
/ALREADY_CLAIMED/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableBuying().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.enableSelling().send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_CLOSED/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("donate", () => {
|
||||
it("donate quote & base token", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("20"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("2000"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.donateBaseToken(decimalStr("2"))
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.donateQuoteToken(decimalStr("500"))
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10666666666666666666"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"1166666666666666666666"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
"21333333333333333333"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
"2333333333333333333333"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2));
|
||||
|
||||
await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
"100666666666666666666"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp2).call(),
|
||||
"101333333333333333334"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
"10166666666666666666666"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp2).call(),
|
||||
"10333333333333333333334"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("retrieve", () => {
|
||||
it("retrieve base token", async () => {
|
||||
await ctx.BASE.methods
|
||||
.transfer(ctx.DODO.options.address, decimalStr("1"))
|
||||
.send(ctx.sendParam(trader));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.retrieve(ctx.BASE.options.address, decimalStr("1"))
|
||||
.send(ctx.sendParam(trader)),
|
||||
/NOT_OWNER/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.retrieve(ctx.BASE.options.address, decimalStr("2"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
await ctx.DODO.methods
|
||||
.retrieve(ctx.BASE.options.address, decimalStr("1"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Deployer).call(),
|
||||
decimalStr("1")
|
||||
);
|
||||
});
|
||||
|
||||
it("retrieve quote token", async () => {
|
||||
await ctx.QUOTE.methods
|
||||
.transfer(ctx.DODO.options.address, decimalStr("1"))
|
||||
.send(ctx.sendParam(trader));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.retrieve(ctx.QUOTE.options.address, decimalStr("2"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_QUOTE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
await ctx.DODO.methods
|
||||
.retrieve(ctx.QUOTE.options.address, decimalStr("1"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(),
|
||||
decimalStr("1")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("revert cases", () => {
|
||||
it("k revert cases", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setK(decimalStr("1"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/K>=1/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setK(decimalStr("0"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/K=0/
|
||||
);
|
||||
});
|
||||
|
||||
it("fee revert cases", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setLiquidityProviderFeeRate(decimalStr("0.999"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/FEE_RATE>=1/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.setMaintainerFeeRate(decimalStr("0.998"))
|
||||
.send(ctx.sendParam(ctx.Deployer)),
|
||||
/FEE_RATE>=1/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr, gweiStr } from './utils/Converter';
|
||||
import BigNumber from "bignumber.js";
|
||||
import * as assert from "assert"
|
||||
|
||||
let lp1: string
|
||||
let lp2: string
|
||||
let trader: string
|
||||
let hacker: string
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"))
|
||||
lp1 = ctx.spareAccounts[0]
|
||||
lp2 = ctx.spareAccounts[1]
|
||||
trader = ctx.spareAccounts[2]
|
||||
hacker = ctx.spareAccounts[3]
|
||||
await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000"))
|
||||
await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000"))
|
||||
await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000"))
|
||||
await ctx.mintTestToken(hacker, decimalStr("10000"), decimalStr("1000000"))
|
||||
await ctx.approveDODO(lp1)
|
||||
await ctx.approveDODO(lp2)
|
||||
await ctx.approveDODO(trader)
|
||||
await ctx.approveDODO(hacker)
|
||||
}
|
||||
|
||||
describe("Attacks", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext()
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
describe("Price offset attack", () => {
|
||||
/*
|
||||
attack describe:
|
||||
1. hacker deposit a great number of base token
|
||||
2. hacker buy base token
|
||||
3. hacker withdraw a great number of base token
|
||||
4. hacker sell or buy base token to finish the arbitrage loop
|
||||
|
||||
expected:
|
||||
1. hacker won't earn any quote token or sell base token with price better than what dodo provides
|
||||
2. quote token lp and base token lp have no loss
|
||||
|
||||
Same in quote direction
|
||||
*/
|
||||
it("attack on base token", async () => {
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1))
|
||||
let hackerInitBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
let hackerInitQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call())
|
||||
// attack step 1
|
||||
await ctx.DODO.methods.depositBase(decimalStr("5000")).send(ctx.sendParam(hacker))
|
||||
// attack step 2
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("9.5"), decimalStr("2000"), "0x").send(ctx.sendParam(hacker))
|
||||
// attack step 3
|
||||
await ctx.DODO.methods.withdrawBase(decimalStr("5000")).send(ctx.sendParam(hacker))
|
||||
// attack step 4
|
||||
let hackerTempBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
if (hackerTempBaseBalance.isGreaterThan(hackerInitBaseBalance)) {
|
||||
await ctx.DODO.methods.sellBaseToken(hackerTempBaseBalance.minus(hackerInitBaseBalance).toString(), "0", "0x").send(ctx.sendParam(hacker))
|
||||
} else {
|
||||
await ctx.DODO.methods.buyBaseToken(hackerInitBaseBalance.minus(hackerTempBaseBalance).toString(), decimalStr("5000"), "0x").send(ctx.sendParam(hacker))
|
||||
}
|
||||
|
||||
// expected hacker no profit
|
||||
let hackerBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
let hackerQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call())
|
||||
|
||||
assert.ok(hackerBaseBalance.isLessThanOrEqualTo(hackerInitBaseBalance))
|
||||
assert.ok(hackerQuoteBalance.isLessThanOrEqualTo(hackerInitQuoteBalance))
|
||||
|
||||
// expected lp no loss
|
||||
let lpBaseBalance = new BigNumber(await ctx.DODO.methods.getLpBaseBalance(lp1).call())
|
||||
let lpQuoteBalance = new BigNumber(await ctx.DODO.methods.getLpQuoteBalance(lp1).call())
|
||||
|
||||
assert.ok(lpBaseBalance.isGreaterThanOrEqualTo(decimalStr("10")))
|
||||
assert.ok(lpQuoteBalance.isGreaterThanOrEqualTo(decimalStr("1000")))
|
||||
})
|
||||
|
||||
it("attack on quote token", async () => {
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1))
|
||||
let hackerInitBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
let hackerInitQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call())
|
||||
|
||||
// attack step 1
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("100000")).send(ctx.sendParam(hacker))
|
||||
// attack step 2
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("9"), decimalStr("500"), "0x").send(ctx.sendParam(hacker))
|
||||
// attack step 3
|
||||
await ctx.DODO.methods.withdrawQuote(decimalStr("100000")).send(ctx.sendParam(hacker))
|
||||
// attack step 4
|
||||
let hackerTempBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
if (hackerTempBaseBalance.isGreaterThan(hackerInitBaseBalance)) {
|
||||
await ctx.DODO.methods.sellBaseToken(hackerTempBaseBalance.minus(hackerInitBaseBalance).toString(), "0", "0x").send(ctx.sendParam(hacker))
|
||||
} else {
|
||||
await ctx.DODO.methods.buyBaseToken(hackerInitBaseBalance.minus(hackerTempBaseBalance).toString(), decimalStr("5000"), "0x").send(ctx.sendParam(hacker))
|
||||
}
|
||||
|
||||
// expected hacker no profit
|
||||
let hackerBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call())
|
||||
let hackerQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call())
|
||||
|
||||
assert.ok(hackerBaseBalance.isLessThanOrEqualTo(hackerInitBaseBalance))
|
||||
assert.ok(hackerQuoteBalance.isLessThanOrEqualTo(hackerInitQuoteBalance))
|
||||
|
||||
// expected lp no loss
|
||||
let lpBaseBalance = new BigNumber(await ctx.DODO.methods.getLpBaseBalance(lp1).call())
|
||||
let lpQuoteBalance = new BigNumber(await ctx.DODO.methods.getLpQuoteBalance(lp1).call())
|
||||
|
||||
assert.ok(lpBaseBalance.isGreaterThanOrEqualTo(decimalStr("10")))
|
||||
assert.ok(lpQuoteBalance.isGreaterThanOrEqualTo(decimalStr("1000")))
|
||||
})
|
||||
})
|
||||
|
||||
describe("Front run attack", () => {
|
||||
/*
|
||||
attack describe:
|
||||
hacker tries to front run oracle updating by sending tx with higher gas price
|
||||
|
||||
expected:
|
||||
revert tx
|
||||
*/
|
||||
it("front run", async () => {
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1))
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x").send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), /GAS_PRICE_EXCEED/
|
||||
)
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("200"), "0x").send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), /GAS_PRICE_EXCEED/
|
||||
)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,233 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
import * as assert from 'assert';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import { TransactionReceipt } from 'web3-core';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
|
||||
import {
|
||||
DefaultDODOContextInitConfig,
|
||||
DODOContext,
|
||||
getDODOContext,
|
||||
} from './utils/DVMContext';
|
||||
import * as contracts from './utils/Contracts';
|
||||
import { decimalStr, MAX_UINT256 } from './utils/Converter';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let lp: string;
|
||||
let trader: string;
|
||||
let DODOEthProxy: Contract;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
// switch ctx to eth proxy mode
|
||||
const WETH = await contracts.newContract(contracts.WETH_CONTRACT_NAME);
|
||||
await ctx.DODOZoo.methods
|
||||
.breedDODO(
|
||||
ctx.Maintainer,
|
||||
WETH.options.address,
|
||||
ctx.QUOTE.options.address,
|
||||
ctx.ORACLE.options.address,
|
||||
DefaultDODOContextInitConfig.lpFeeRate,
|
||||
DefaultDODOContextInitConfig.mtFeeRate,
|
||||
DefaultDODOContextInitConfig.k,
|
||||
DefaultDODOContextInitConfig.gasPriceLimit
|
||||
)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
ctx.DODO = contracts.getContractWithAddress(
|
||||
contracts.DODO_CONTRACT_NAME,
|
||||
await ctx.DODOZoo.methods
|
||||
.getDODO(WETH.options.address, ctx.QUOTE.options.address)
|
||||
.call()
|
||||
);
|
||||
await ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
ctx.BASE = WETH;
|
||||
|
||||
DODOEthProxy = await contracts.newContract(
|
||||
contracts.DODO_ETH_PROXY_CONTRACT_NAME,
|
||||
[ctx.DODOZoo.options.address, WETH.options.address]
|
||||
);
|
||||
|
||||
// env
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
await ctx.approveDODO(lp);
|
||||
await ctx.approveDODO(trader);
|
||||
|
||||
await ctx.QUOTE.methods
|
||||
.mint(lp, decimalStr("1000"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.QUOTE.methods
|
||||
.mint(trader, decimalStr("1000"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.QUOTE.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
describe("DODO ETH PROXY", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
await ctx.QUOTE.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(trader));
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
const depositAmount = "10";
|
||||
await DODOEthProxy.methods
|
||||
.depositEthAsBase(decimalStr(depositAmount), ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(lp, depositAmount));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("buy&sell eth directly", () => {
|
||||
it("buy", async () => {
|
||||
const buyAmount = "1";
|
||||
await logGas(
|
||||
DODOEthProxy.methods.buyEthWithToken(
|
||||
ctx.QUOTE.options.address,
|
||||
decimalStr(buyAmount),
|
||||
decimalStr("200")
|
||||
),
|
||||
ctx.sendParam(trader),
|
||||
"buy ETH with token directly"
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("8.999")
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"898581839502056240973"
|
||||
);
|
||||
});
|
||||
it("sell", async () => {
|
||||
const sellAmount = "1";
|
||||
await logGas(
|
||||
DODOEthProxy.methods.sellEthToToken(
|
||||
ctx.QUOTE.options.address,
|
||||
decimalStr(sellAmount),
|
||||
decimalStr("50")
|
||||
),
|
||||
ctx.sendParam(trader, sellAmount),
|
||||
"sell ETH to token directly"
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("11")
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1098617454226610630663"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("withdraw eth directly", () => {
|
||||
it("withdraw", async () => {
|
||||
const withdrawAmount = decimalStr("5");
|
||||
const baseLpTokenAddress = await ctx.DODO.methods
|
||||
._BASE_CAPITAL_TOKEN_()
|
||||
.call();
|
||||
const baseLpToken = contracts.getContractWithAddress(
|
||||
contracts.TEST_ERC20_CONTRACT_NAME,
|
||||
baseLpTokenAddress
|
||||
);
|
||||
await baseLpToken.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(lp));
|
||||
const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp);
|
||||
const txReceipt: TransactionReceipt = await DODOEthProxy.methods
|
||||
.withdrawEthAsBase(withdrawAmount, ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp).call(),
|
||||
withdrawAmount
|
||||
);
|
||||
const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash);
|
||||
const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed);
|
||||
const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp);
|
||||
assert.ok(
|
||||
new BigNumber(lpEthBalanceBefore)
|
||||
.plus(withdrawAmount)
|
||||
.minus(ethSpentOnGas)
|
||||
.eq(lpEthBalanceAfter)
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw all", async () => {
|
||||
const withdrawAmount = decimalStr("10");
|
||||
const baseLpTokenAddress = await ctx.DODO.methods
|
||||
._BASE_CAPITAL_TOKEN_()
|
||||
.call();
|
||||
const baseLpToken = contracts.getContractWithAddress(
|
||||
contracts.TEST_ERC20_CONTRACT_NAME,
|
||||
baseLpTokenAddress
|
||||
);
|
||||
await baseLpToken.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(lp));
|
||||
const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp);
|
||||
const txReceipt: TransactionReceipt = await DODOEthProxy.methods
|
||||
.withdrawAllEthAsBase(ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp).call(),
|
||||
"0"
|
||||
);
|
||||
const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash);
|
||||
const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed);
|
||||
const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp);
|
||||
assert.ok(
|
||||
new BigNumber(lpEthBalanceBefore)
|
||||
.plus(withdrawAmount)
|
||||
.minus(ethSpentOnGas)
|
||||
.eq(lpEthBalanceAfter)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("revert cases", () => {
|
||||
it("value not match", async () => {
|
||||
await assert.rejects(
|
||||
DODOEthProxy.methods
|
||||
.sellEthToToken(
|
||||
ctx.QUOTE.options.address,
|
||||
decimalStr("1"),
|
||||
decimalStr("50")
|
||||
)
|
||||
.send(ctx.sendParam(trader, "2")),
|
||||
/ETH_AMOUNT_NOT_MATCH/
|
||||
);
|
||||
await assert.rejects(
|
||||
DODOEthProxy.methods
|
||||
.depositEthAsBase(decimalStr("1"), ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(lp, "2")),
|
||||
/ETH_AMOUNT_NOT_MATCH/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
import * as assert from 'assert';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { TransactionReceipt } from 'web3-core';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
|
||||
import {
|
||||
DefaultDODOContextInitConfig,
|
||||
DODOContext,
|
||||
getDODOContext,
|
||||
} from './utils/DVMContext';
|
||||
import * as contracts from './utils/Contracts';
|
||||
import { decimalStr, MAX_UINT256 } from './utils/Converter';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let lp: string;
|
||||
let trader: string;
|
||||
let DODOEthProxy: Contract;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
// switch ctx to eth proxy mode
|
||||
const WETH = await contracts.newContract(contracts.WETH_CONTRACT_NAME);
|
||||
await ctx.DODOZoo.methods
|
||||
.breedDODO(
|
||||
ctx.Maintainer,
|
||||
ctx.BASE.options.address,
|
||||
WETH.options.address,
|
||||
ctx.ORACLE.options.address,
|
||||
DefaultDODOContextInitConfig.lpFeeRate,
|
||||
DefaultDODOContextInitConfig.mtFeeRate,
|
||||
DefaultDODOContextInitConfig.k,
|
||||
DefaultDODOContextInitConfig.gasPriceLimit
|
||||
)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
ctx.DODO = contracts.getContractWithAddress(
|
||||
contracts.DODO_CONTRACT_NAME,
|
||||
await ctx.DODOZoo.methods
|
||||
.getDODO(ctx.BASE.options.address, WETH.options.address)
|
||||
.call()
|
||||
);
|
||||
await ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
ctx.QUOTE = WETH;
|
||||
|
||||
DODOEthProxy = await contracts.newContract(
|
||||
contracts.DODO_ETH_PROXY_CONTRACT_NAME,
|
||||
[ctx.DODOZoo.options.address, WETH.options.address]
|
||||
);
|
||||
|
||||
// env
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
await ctx.setOraclePrice(decimalStr("0.01"));
|
||||
await ctx.approveDODO(lp);
|
||||
await ctx.approveDODO(trader);
|
||||
|
||||
await ctx.BASE.methods
|
||||
.mint(lp, decimalStr("1000"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.BASE.methods
|
||||
.mint(trader, decimalStr("1000"))
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.BASE.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
describe("DODO ETH PROXY", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
await ctx.BASE.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(trader));
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
let depositAmount = "10";
|
||||
await DODOEthProxy.methods
|
||||
.depositEthAsQuote(decimalStr(depositAmount), ctx.BASE.options.address)
|
||||
.send(ctx.sendParam(lp, depositAmount));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("buy&sell eth directly", () => {
|
||||
it("buy", async () => {
|
||||
const maxPayEthAmount = "2.1";
|
||||
const ethInPoolBefore = decimalStr("10");
|
||||
const traderEthBalanceBefore = await ctx.Web3.eth.getBalance(trader);
|
||||
const txReceipt: TransactionReceipt = await logGas(
|
||||
DODOEthProxy.methods.buyTokenWithEth(
|
||||
ctx.BASE.options.address,
|
||||
decimalStr("200"),
|
||||
decimalStr(maxPayEthAmount)
|
||||
),
|
||||
ctx.sendParam(trader, maxPayEthAmount),
|
||||
"buy token with ETH directly"
|
||||
);
|
||||
const ethInPoolAfter = "12056338203652739553";
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
ethInPoolAfter
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("1200")
|
||||
);
|
||||
const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash);
|
||||
const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed);
|
||||
const traderEthBalanceAfter = await ctx.Web3.eth.getBalance(trader);
|
||||
|
||||
const totalEthBefore = new BigNumber(traderEthBalanceBefore).plus(
|
||||
ethInPoolBefore
|
||||
);
|
||||
const totalEthAfter = new BigNumber(traderEthBalanceAfter)
|
||||
.plus(ethSpentOnGas)
|
||||
.plus(ethInPoolAfter);
|
||||
assert.ok(totalEthBefore.eq(totalEthAfter));
|
||||
});
|
||||
it("sell", async () => {
|
||||
const minReceiveEthAmount = "0.45";
|
||||
await logGas(
|
||||
DODOEthProxy.methods.sellTokenToEth(
|
||||
ctx.BASE.options.address,
|
||||
decimalStr("50"),
|
||||
decimalStr(minReceiveEthAmount)
|
||||
),
|
||||
ctx.sendParam(trader),
|
||||
"sell token to ETH directly"
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"9503598324131652490"
|
||||
);
|
||||
assert.strictEqual(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("950")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("withdraw eth directly", () => {
|
||||
it("withdraw", async () => {
|
||||
const withdrawAmount = decimalStr("5");
|
||||
const quoteLpTokenAddress = await ctx.DODO.methods
|
||||
._QUOTE_CAPITAL_TOKEN_()
|
||||
.call();
|
||||
const quoteLpToken = contracts.getContractWithAddress(
|
||||
contracts.TEST_ERC20_CONTRACT_NAME,
|
||||
quoteLpTokenAddress
|
||||
);
|
||||
await quoteLpToken.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(lp));
|
||||
const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp);
|
||||
const txReceipt: TransactionReceipt = await DODOEthProxy.methods
|
||||
.withdrawEthAsQuote(withdrawAmount, ctx.BASE.options.address)
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp).call(),
|
||||
withdrawAmount
|
||||
);
|
||||
const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash);
|
||||
const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed);
|
||||
const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp);
|
||||
assert.ok(
|
||||
new BigNumber(lpEthBalanceBefore)
|
||||
.plus(withdrawAmount)
|
||||
.minus(ethSpentOnGas)
|
||||
.eq(lpEthBalanceAfter)
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw all", async () => {
|
||||
const withdrawAmount = decimalStr("10");
|
||||
const quoteLpTokenAddress = await ctx.DODO.methods
|
||||
._QUOTE_CAPITAL_TOKEN_()
|
||||
.call();
|
||||
const quoteLpToken = contracts.getContractWithAddress(
|
||||
contracts.TEST_ERC20_CONTRACT_NAME,
|
||||
quoteLpTokenAddress
|
||||
);
|
||||
await quoteLpToken.methods
|
||||
.approve(DODOEthProxy.options.address, MAX_UINT256)
|
||||
.send(ctx.sendParam(lp));
|
||||
const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp);
|
||||
const txReceipt: TransactionReceipt = await DODOEthProxy.methods
|
||||
.withdrawAllEthAsQuote(ctx.BASE.options.address)
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
assert.strictEqual(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp).call(),
|
||||
"0"
|
||||
);
|
||||
const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash);
|
||||
const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed);
|
||||
const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp);
|
||||
assert.ok(
|
||||
new BigNumber(lpEthBalanceBefore)
|
||||
.plus(withdrawAmount)
|
||||
.minus(ethSpentOnGas)
|
||||
.eq(lpEthBalanceAfter)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("revert cases", () => {
|
||||
it("value not match", async () => {
|
||||
await assert.rejects(
|
||||
DODOEthProxy.methods
|
||||
.buyTokenWithEth(
|
||||
ctx.BASE.options.address,
|
||||
decimalStr("50"),
|
||||
decimalStr("1")
|
||||
)
|
||||
.send(ctx.sendParam(trader, "2")),
|
||||
/ETH_AMOUNT_NOT_MATCH/
|
||||
);
|
||||
await assert.rejects(
|
||||
DODOEthProxy.methods
|
||||
.depositEthAsQuote(decimalStr("1"), ctx.BASE.options.address)
|
||||
.send(ctx.sendParam(lp, "2")),
|
||||
/ETH_AMOUNT_NOT_MATCH/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import * as assert from "assert"
|
||||
import { newContract, TEST_ERC20_CONTRACT_NAME, getContractWithAddress, DODO_CONTRACT_NAME } from './utils/Contracts';
|
||||
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> { }
|
||||
|
||||
describe("DODO ZOO", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext()
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
describe("Breed new dodo", () => {
|
||||
it("could not deploy the same dodo", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, ctx.BASE.options.address, ctx.QUOTE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_REGISTERED/
|
||||
)
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, ctx.QUOTE.options.address, ctx.BASE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_REGISTERED/
|
||||
)
|
||||
})
|
||||
|
||||
it("breed new dodo", async () => {
|
||||
let newBase = await newContract(TEST_ERC20_CONTRACT_NAME, ["AnotherBase", 18])
|
||||
let newQuote = await newContract(TEST_ERC20_CONTRACT_NAME, ["AnotherQuote", 18])
|
||||
await assert.rejects(
|
||||
ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, newBase.options.address, newQuote.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Maintainer)),
|
||||
/NOT_OWNER/
|
||||
)
|
||||
await ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, newBase.options.address, newQuote.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
let newDODO = getContractWithAddress(DODO_CONTRACT_NAME, await ctx.DODOZoo.methods.getDODO(newBase.options.address, newQuote.options.address).call())
|
||||
assert.equal(await newDODO.methods._BASE_TOKEN_().call(), newBase.options.address)
|
||||
assert.equal(await newDODO.methods._QUOTE_TOKEN_().call(), newQuote.options.address)
|
||||
|
||||
// could not init twice
|
||||
await assert.rejects(
|
||||
newDODO.methods.init(ctx.Deployer, ctx.Supervisor, ctx.Maintainer, ctx.QUOTE.options.address, ctx.BASE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_INITIALIZED/
|
||||
)
|
||||
|
||||
// console.log(await ctx.DODOZoo.methods.getDODOs().call())
|
||||
})
|
||||
|
||||
// it.only("remove dodo", async () => {
|
||||
// console.log(await ctx.DODOZoo.methods.getDODOs().call())
|
||||
// await ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
// console.log(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call())
|
||||
// console.log(await ctx.DODOZoo.methods.getDODOs().call())
|
||||
// })
|
||||
|
||||
it("dodo register control flow", async () => {
|
||||
await ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
assert.equal(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call(), "0x0000000000000000000000000000000000000000")
|
||||
await assert.rejects(
|
||||
ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_NOT_REGISTERED/
|
||||
)
|
||||
await ctx.DODOZoo.methods.addDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
assert.equal(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call(), ctx.DODO.options.address)
|
||||
await assert.rejects(
|
||||
ctx.DODOZoo.methods.addDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)),
|
||||
/DODO_REGISTERED/
|
||||
)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
@@ -1,925 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr } from './utils/Converter';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let lp1: string;
|
||||
let lp2: string;
|
||||
let trader: string;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
lp1 = ctx.spareAccounts[0];
|
||||
lp2 = ctx.spareAccounts[1];
|
||||
trader = ctx.spareAccounts[2];
|
||||
await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.approveDODO(lp1);
|
||||
await ctx.approveDODO(lp2);
|
||||
await ctx.approveDODO(trader);
|
||||
}
|
||||
|
||||
describe("LiquidityProvider", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("R equals to ONE", () => {
|
||||
it("multi lp deposit & withdraw", async () => {
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("0")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("0")
|
||||
);
|
||||
|
||||
await logGas(
|
||||
ctx.DODO.methods.depositBase(decimalStr("10")),
|
||||
ctx.sendParam(lp1),
|
||||
"deposit base"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("90")
|
||||
);
|
||||
await logGas(
|
||||
ctx.DODO.methods.depositQuote(decimalStr("1000")),
|
||||
ctx.sendParam(lp1),
|
||||
"deposit quote"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("9000")
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("3"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("70"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
decimalStr("3")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
decimalStr("70")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("13")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
decimalStr("1070")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("5"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("5")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("95")
|
||||
);
|
||||
await ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("100"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("900")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("9100")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1));
|
||||
assert.equal(await ctx.DODO.methods.getLpBaseBalance(lp1).call(), "0");
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1));
|
||||
assert.equal(await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), "0");
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("10000")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("R is ABOVE ONE", () => {
|
||||
it("deposit", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10010841132009222923"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("5"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("100"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
// lp1 & lp2 would both have profit because the curve becomes flatter
|
||||
// but the withdraw penalty is greater than this free profit
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10163234422929069723"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
"5076114129127759292"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(),
|
||||
"228507420047606093"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods
|
||||
.getWithdrawQuotePenalty(decimalStr("100"))
|
||||
.call(),
|
||||
"0"
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("4")).call(),
|
||||
"1065045389392391665"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods
|
||||
.getWithdrawQuotePenalty(decimalStr("100"))
|
||||
.call(),
|
||||
"0"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("4"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
"92934954610607608335"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
"2060045389392391665"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"7075045389392391665"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("100"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("9100")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1451951805416248746119"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
decimalStr("900")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("R is BELOW ONE", () => {
|
||||
it("deposit", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"1000978629616255276996"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("500"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("5"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"1012529270910521756641"
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
decimalStr("5")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
"505769674273013522654"
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(),
|
||||
"0"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods
|
||||
.getWithdrawQuotePenalty(decimalStr("500"))
|
||||
.call(),
|
||||
"17320315567280002300"
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("4")).call(),
|
||||
"0"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods
|
||||
.getWithdrawQuotePenalty(decimalStr("100"))
|
||||
.call(),
|
||||
"7389428846238900753"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("100"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
"9092610571153761099247"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"447655402437037253588"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"908310739520405637520"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("4"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("94")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("11")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
decimalStr("6")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Oracle changes", () => {
|
||||
it("base side lp don't has pnl when R is BELOW ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("80"));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"914362409397559037208"
|
||||
);
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("120"));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"1085284653936129406317"
|
||||
);
|
||||
});
|
||||
|
||||
it("quote side lp don't has pnl when R is ABOVE ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("600"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("80"));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"11138732839027528597"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("120"));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"9234731968726215588"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Transfer lp token", () => {
|
||||
it("transfer", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.BaseCapital.methods
|
||||
.transfer(lp2, decimalStr("5"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.QuoteCapital.methods
|
||||
.transfer(lp2, decimalStr("5"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
|
||||
await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp2).call(),
|
||||
decimalStr("105")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp2).call(),
|
||||
decimalStr("10005")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Deposit & transfer to other account", () => {
|
||||
it("base token", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBaseTo(lp2, decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.withdrawBaseTo(trader, decimalStr("5"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.withdrawAllBaseTo(ctx.Supervisor)
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("90")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp2).call(),
|
||||
decimalStr("100")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("105")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Supervisor).call(),
|
||||
decimalStr("5")
|
||||
);
|
||||
});
|
||||
|
||||
it("quote token", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuoteTo(lp2, decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.withdrawQuoteTo(trader, decimalStr("500"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.withdrawAllQuoteTo(ctx.Supervisor)
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp1).call(),
|
||||
decimalStr("9000")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(lp2).call(),
|
||||
decimalStr("10000")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
decimalStr("10500")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Supervisor).call(),
|
||||
decimalStr("500")
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Corner cases", () => {
|
||||
it("single side deposit", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken("5015841132009222923", decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"10010841132009222923"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1103903610832497492"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(),
|
||||
"1103903610832497493"
|
||||
);
|
||||
});
|
||||
|
||||
it("single side deposit & lp deposit when R isn't equal to ONE", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(),
|
||||
"1"
|
||||
);
|
||||
assert.equal(await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), "1");
|
||||
});
|
||||
|
||||
it("single side deposit (base) & oracle change introduces loss", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("120"));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("4"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("1"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2");
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"9234731968726215603"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1105993618321025490"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(),
|
||||
"7221653398290521828"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
"7221653398290521884"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"9234731968726215603"
|
||||
);
|
||||
});
|
||||
|
||||
it("single side deposit (base) & oracle change introduces profit", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("80"));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("4"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("4"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2");
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"11138732839027528584"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1105408308382702868"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(),
|
||||
"21553269260529319669"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp2).call(),
|
||||
"21553269260529319697"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"11138732839027528584"
|
||||
);
|
||||
});
|
||||
|
||||
it("single side deposit (quote) & oracle change introduces loss", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await ctx.setOraclePrice(decimalStr("80"));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("4"), decimalStr("600"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("0.99"), decimalStr("500"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "1");
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"9980000000000000"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"914362409397559035414"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.depositBase("1").send(ctx.sendParam(lp2));
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getBaseCapitalBalanceOf(lp2).call(),
|
||||
"10247647352975730"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
"10247647352975730"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp1).call(),
|
||||
"914362409397559035414"
|
||||
);
|
||||
});
|
||||
|
||||
it("deposit and withdraw immediately", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10010841132009222923"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("5"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10163234422929069723"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp2).call(),
|
||||
"5076114129127759292"
|
||||
);
|
||||
|
||||
await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2));
|
||||
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(lp2).call(),
|
||||
"99841132414635941792"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpBaseBalance(lp1).call(),
|
||||
"10182702153814588648"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Revert cases", () => {
|
||||
it("withdraw base amount exceeds DODO balance", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawBase(decimalStr("6")).send(ctx.sendParam(lp1)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw quote amount exceeds DODO balance", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("5"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("600"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/DODO_QUOTE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)),
|
||||
/DODO_QUOTE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw base could not afford penalty", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("9"), decimalStr("10000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("0.5"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/PENALTY_EXCEED/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("10")).call(),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw quote could not afford penalty", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("10"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("200"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/PENALTY_EXCEED/
|
||||
);
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.getWithdrawQuotePenalty(decimalStr("1000")).call(),
|
||||
/DODO_QUOTE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw all base could not afford penalty", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("9.5"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("0.5"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("9"), decimalStr("10000"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("0.5"))
|
||||
.send(ctx.sendParam(lp2)),
|
||||
/PENALTY_EXCEED/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw all quote could not afford penalty", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("800"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("200"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("10"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("200"))
|
||||
.send(ctx.sendParam(lp2)),
|
||||
/PENALTY_EXCEED/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw amount exceeds lp balance", async () => {
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositBase(decimalStr("10"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp1));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp2));
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawBase(decimalStr("11"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/LP_BASE_CAPITAL_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("1100"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/LP_QUOTE_CAPITAL_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("withdraw when there is no lp", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.withdrawBase(decimalStr("1")).send(ctx.sendParam(lp1)),
|
||||
/NO_BASE_LP/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.withdrawQuote(decimalStr("1"))
|
||||
.send(ctx.sendParam(lp1)),
|
||||
/NO_QUOTE_LP/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr, gweiStr } from './utils/Converter';
|
||||
import * as assert from "assert"
|
||||
|
||||
let lp: string
|
||||
let trader: string
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("10"))
|
||||
|
||||
lp = ctx.spareAccounts[0]
|
||||
trader = ctx.spareAccounts[1]
|
||||
await ctx.approveDODO(lp)
|
||||
await ctx.approveDODO(trader)
|
||||
|
||||
await ctx.mintTestToken(lp, decimalStr("10000"), decimalStr("10000000"))
|
||||
await ctx.mintTestToken(trader, decimalStr("0"), decimalStr("10000000"))
|
||||
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10000")).send(ctx.sendParam(lp))
|
||||
}
|
||||
|
||||
describe("Trader", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
let dodoContextInitConfig = {
|
||||
lpFeeRate: decimalStr("0"),
|
||||
mtFeeRate: decimalStr("0"),
|
||||
k: decimalStr("0.99"), // nearly one
|
||||
gasPriceLimit: gweiStr("100"),
|
||||
}
|
||||
ctx = await getDODOContext(dodoContextInitConfig)
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
// price change quickly
|
||||
describe("Trade long tail coin", () => {
|
||||
it("price discover", async () => {
|
||||
// 10% depth
|
||||
// avg price = 11.137
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("1000"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9988900000000000000000000")
|
||||
|
||||
// 20% depth
|
||||
// avg price = 12.475
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("2000"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9975049999999999999970000")
|
||||
|
||||
// 50% depth
|
||||
// avg price = 19.9
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("3000"), decimalStr("300000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("5000"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9900499999999999999970000")
|
||||
|
||||
// 80% depth
|
||||
// avg price = 49.6
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("3000"), decimalStr("300000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("8000"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9603199999999999999970000")
|
||||
})
|
||||
|
||||
it("user has no pnl if buy and sell immediately", async () => {
|
||||
// lp buy
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(lp))
|
||||
|
||||
// trader buy and sell
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader))
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("1000"), decimalStr("0"), "0x").send(ctx.sendParam(trader))
|
||||
|
||||
// no profit or loss (may have precision problems)
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), "0")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9999999999999999999970000")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr, MAX_UINT256 } from './utils/Converter';
|
||||
// import * as assert from "assert"
|
||||
import { newContract, DODO_TOKEN_CONTRACT_NAME, DODO_MINE_NAME, TEST_ERC20_CONTRACT_NAME, getContractWithAddress, DODO_MINE_READER_NAME } from './utils/Contracts';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
import { assert } from 'chai';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let BaseDLP: Contract
|
||||
let QuoteDLP: Contract
|
||||
let DODOToken: Contract
|
||||
let DODOMine: Contract
|
||||
let DODOMineReader: Contract
|
||||
let lp1: string;
|
||||
let lp2: string;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
|
||||
lp1 = ctx.spareAccounts[0];
|
||||
lp2 = ctx.spareAccounts[1];
|
||||
await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000"));
|
||||
await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000"));
|
||||
|
||||
await ctx.approveDODO(lp1);
|
||||
await ctx.approveDODO(lp2);
|
||||
|
||||
await ctx.DODO.methods.depositBase(decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp1))
|
||||
|
||||
await ctx.DODO.methods.depositBase(decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp2))
|
||||
|
||||
DODOToken = await newContract(DODO_TOKEN_CONTRACT_NAME)
|
||||
DODOMine = await newContract(DODO_MINE_NAME, [DODOToken.options.address, (await ctx.Web3.eth.getBlockNumber()).toString()])
|
||||
DODOMineReader = await newContract(DODO_MINE_READER_NAME)
|
||||
|
||||
BaseDLP = await getContractWithAddress(TEST_ERC20_CONTRACT_NAME, await ctx.DODO.methods._BASE_CAPITAL_TOKEN_().call())
|
||||
QuoteDLP = await getContractWithAddress(TEST_ERC20_CONTRACT_NAME, await ctx.DODO.methods._QUOTE_CAPITAL_TOKEN_().call())
|
||||
|
||||
await BaseDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp1))
|
||||
await QuoteDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp1))
|
||||
|
||||
await BaseDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp2))
|
||||
await QuoteDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp2))
|
||||
|
||||
await DODOMine.methods.setReward(decimalStr("100"), true).send(ctx.sendParam(ctx.Deployer))
|
||||
await DODOMine.methods.addLpToken(BaseDLP.options.address, "1", true).send(ctx.sendParam(ctx.Deployer))
|
||||
await DODOMine.methods.addLpToken(QuoteDLP.options.address, "2", true).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
const rewardVault = await DODOMine.methods.dodoRewardVault().call()
|
||||
await DODOToken.methods.transfer(rewardVault, decimalStr("100000000")).send(ctx.sendParam(ctx.Deployer))
|
||||
}
|
||||
|
||||
describe("Lock DODO Token", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext()
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
describe("Lp Deposit", () => {
|
||||
it("single lp deposit", async () => {
|
||||
await logGas(DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")), ctx.sendParam(lp1), "deposit")
|
||||
await ctx.EVM.fastMove(100)
|
||||
assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "3333333333333333333300")
|
||||
assert.equal(await DODOMine.methods.getDlpMiningSpeed(BaseDLP.options.address).call(), "33333333333333333333")
|
||||
})
|
||||
|
||||
it("multi lp deposit", async () => {
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await ctx.EVM.fastMove(100)
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
await ctx.EVM.fastMove(100)
|
||||
assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "5033333333333333333200")
|
||||
assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp2).call(), "1666666666666666666600")
|
||||
|
||||
await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await ctx.EVM.fastMove(100)
|
||||
await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
await ctx.EVM.fastMove(100)
|
||||
assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp1).call(), "10066666666666666666600")
|
||||
assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp2).call(), "3333333333333333333300")
|
||||
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "18466666666666666666500")
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp2).call(), "8366666666666666666600")
|
||||
})
|
||||
|
||||
it.only("lp multi deposit and withdraw", async () => {
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await ctx.EVM.fastMove(100)
|
||||
await logGas(DODOMine.methods.withdraw(BaseDLP.options.address, decimalStr("50")), ctx.sendParam(lp1), "withdraw")
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0")
|
||||
assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "1683333333333333333300")
|
||||
assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "1683333333333333333300")
|
||||
await ctx.EVM.fastMove(100)
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("50")).send(ctx.sendParam(lp1))
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0")
|
||||
assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "2805555555555555555500")
|
||||
assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "2805555555555555555500")
|
||||
|
||||
var balance = await DODOMineReader.methods.getUserStakedBalance(DODOMine.options.address, ctx.DODO.options.address, lp1).call()
|
||||
assert.equal(balance.baseBalance, decimalStr("100"))
|
||||
assert.equal(balance.quoteBalance, decimalStr("0"))
|
||||
})
|
||||
|
||||
it("lp claim", async () => {
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
|
||||
await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2))
|
||||
|
||||
await ctx.EVM.fastMove(100)
|
||||
|
||||
await logGas(DODOMine.methods.claim(BaseDLP.options.address), ctx.sendParam(lp1), "claim")
|
||||
assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "0")
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "3433333333333333333200")
|
||||
assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "1749999999999999999900")
|
||||
assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "1749999999999999999900")
|
||||
|
||||
await logGas(DODOMine.methods.claimAll(), ctx.sendParam(lp2), "claim 2 pool")
|
||||
assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp2).call(), "0")
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp2).call(), "0")
|
||||
assert.equal(await DODOMine.methods.getRealizedReward(lp2).call(), "5133333333333333333200")
|
||||
assert.equal(await DODOToken.methods.balanceOf(lp2).call(), "5133333333333333333200")
|
||||
})
|
||||
|
||||
it("lp emergency withdraw", async () => {
|
||||
await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
|
||||
await ctx.EVM.fastMove(100)
|
||||
|
||||
await DODOMine.methods.emergencyWithdraw(QuoteDLP.options.address).send(ctx.sendParam(lp1))
|
||||
|
||||
assert.equal(await QuoteDLP.methods.balanceOf(lp1).call(), decimalStr("10000"))
|
||||
assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp1).call(), "0")
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0")
|
||||
assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "0")
|
||||
assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "0")
|
||||
})
|
||||
|
||||
it("setLpToken", async () => {
|
||||
await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1))
|
||||
await ctx.EVM.fastMove(100)
|
||||
await DODOMine.methods.setLpToken(BaseDLP.options.address, "2", true).send(ctx.sendParam(ctx.Deployer))
|
||||
await ctx.EVM.fastMove(100)
|
||||
|
||||
assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "8366666666666666666600")
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { DODO_REBALANCER_NAME, newContract } from './utils/Contracts';
|
||||
import { decimalStr } from './utils/Converter';
|
||||
|
||||
let lp: string;
|
||||
let trader: string;
|
||||
let rebalancer: Contract;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
await ctx.approveDODO(lp);
|
||||
await ctx.approveDODO(trader);
|
||||
|
||||
await ctx.mintTestToken(lp, decimalStr("10"), decimalStr("1000"));
|
||||
await ctx.mintTestToken(trader, decimalStr("10"), decimalStr("1000"));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBaseTo(lp, decimalStr("10"))
|
||||
.send(ctx.sendParam(lp));
|
||||
await ctx.DODO.methods
|
||||
.depositQuoteTo(lp, decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
rebalancer = await newContract(DODO_REBALANCER_NAME)
|
||||
}
|
||||
|
||||
describe("Trader", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("rebalance", () => {
|
||||
it("R above ONE rebalance", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader))
|
||||
await ctx.DODO.methods.disableTrading().send(ctx.sendParam(ctx.Deployer))
|
||||
await ctx.DODO.methods.transferOwnership(rebalancer.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
await rebalancer.methods.claimOwnership(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await ctx.BASE.methods.transfer(rebalancer.options.address, decimalStr("2")).send(ctx.sendParam(trader))
|
||||
await rebalancer.methods.rebalance(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
assert.equal(await ctx.DODO.methods.getMidPrice().call(), await ctx.DODO.methods.getOraclePrice().call())
|
||||
|
||||
await rebalancer.methods.transferOwnership(ctx.DODO.options.address, ctx.Deployer).send(ctx.sendParam(ctx.Deployer))
|
||||
await ctx.DODO.methods.claimOwnership().send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await rebalancer.methods.retrieve(ctx.BASE.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
await rebalancer.methods.retrieve(ctx.QUOTE.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(ctx.Deployer).call(), "996997569110682237")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(), "101113906016449927750")
|
||||
});
|
||||
|
||||
it("R below ONE rebalance", async () => {
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader))
|
||||
await ctx.DODO.methods.disableTrading().send(ctx.sendParam(ctx.Deployer))
|
||||
await ctx.DODO.methods.transferOwnership(rebalancer.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
await rebalancer.methods.claimOwnership(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await ctx.QUOTE.methods.transfer(rebalancer.options.address, decimalStr("200")).send(ctx.sendParam(trader))
|
||||
await rebalancer.methods.rebalance(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer));
|
||||
|
||||
assert.equal(await ctx.DODO.methods.getMidPrice().call(), await ctx.DODO.methods.getOraclePrice().call())
|
||||
|
||||
await rebalancer.methods.transferOwnership(ctx.DODO.options.address, ctx.Deployer).send(ctx.sendParam(ctx.Deployer))
|
||||
await ctx.DODO.methods.claimOwnership().send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await rebalancer.methods.retrieve(ctx.BASE.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
await rebalancer.methods.retrieve(ctx.QUOTE.options.address).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(ctx.Deployer).call(), "997008973080757726")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(), "101085569972088780856")
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr, gweiStr } from './utils/Converter';
|
||||
import * as assert from "assert"
|
||||
|
||||
let lp: string
|
||||
let trader: string
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("1"))
|
||||
|
||||
lp = ctx.spareAccounts[0]
|
||||
trader = ctx.spareAccounts[1]
|
||||
await ctx.approveDODO(lp)
|
||||
await ctx.approveDODO(trader)
|
||||
|
||||
await ctx.mintTestToken(lp, decimalStr("10000"), decimalStr("10000"))
|
||||
await ctx.mintTestToken(trader, decimalStr("10000"), decimalStr("10000"))
|
||||
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10000")).send(ctx.sendParam(lp))
|
||||
await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp))
|
||||
}
|
||||
|
||||
describe("Trader", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
let dodoContextInitConfig = {
|
||||
lpFeeRate: decimalStr("0.0001"),
|
||||
mtFeeRate: decimalStr("0"),
|
||||
k: gweiStr("1"), // nearly zero
|
||||
gasPriceLimit: gweiStr("100"),
|
||||
}
|
||||
ctx = await getDODOContext(dodoContextInitConfig)
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
describe("Trade stable coin", () => {
|
||||
it("trade with tiny slippage", async () => {
|
||||
// 10% depth avg price 1.000100000111135
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("1001"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("11000"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "8999899999888865431655")
|
||||
|
||||
// 99.9% depth avg price 1.00010109
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("8990"), decimalStr("10000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("19990"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "8990031967806921648")
|
||||
|
||||
// sell to 99.9% depth avg price 0.9999
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("19980"), decimalStr("19970"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("10"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "19986992950440794518402")
|
||||
})
|
||||
|
||||
it("huge sell trading amount", async () => {
|
||||
// trader could sell any number of base token
|
||||
// but the price will drop quickly
|
||||
await ctx.mintTestToken(trader, decimalStr("10000"), decimalStr("0"))
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("20000"), decimalStr("0"), "0x").send(ctx.sendParam(trader))
|
||||
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("0"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "19998999990001000029997")
|
||||
})
|
||||
|
||||
it("huge buy trading amount", async () => {
|
||||
// could not buy all base balance
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods.buyBaseToken(decimalStr("10000"), decimalStr("10010"), "0x").send(ctx.sendParam(trader)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
)
|
||||
|
||||
// when buy amount close to base balance, price will increase quickly
|
||||
await ctx.mintTestToken(trader, decimalStr("0"), decimalStr("10000"))
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("9999"), decimalStr("20000"), "0x").send(ctx.sendParam(trader))
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("19999"))
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9000000119999999900000")
|
||||
})
|
||||
|
||||
it("tiny withdraw penalty", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("9990"), decimalStr("10000"), "0x").send(ctx.sendParam(trader))
|
||||
|
||||
// penalty only 0.2% even if withdraw make pool utilization rate raise to 99.5%
|
||||
assert.equal(await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(), "9981967500000000")
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr, MAX_UINT256 } from './utils/Converter';
|
||||
// import * as assert from "assert"
|
||||
import { newContract, DODO_TOKEN_CONTRACT_NAME, LOCKED_TOKEN_VAULT_CONTRACT_NAME } from './utils/Contracts';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
import * as assert from 'assert';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let DODOToken: Contract
|
||||
let LockedTokenVault: Contract
|
||||
let initTime: any
|
||||
|
||||
let u1: string
|
||||
let u2: string
|
||||
let u3: string
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
u1 = ctx.spareAccounts[0];
|
||||
u2 = ctx.spareAccounts[1];
|
||||
u3 = ctx.spareAccounts[2];
|
||||
|
||||
initTime = (await ctx.Web3.eth.getBlock(await ctx.Web3.eth.getBlockNumber())).timestamp;
|
||||
DODOToken = await newContract(DODO_TOKEN_CONTRACT_NAME)
|
||||
|
||||
// release after 1 day, cliff 10% and vest in 1 day
|
||||
LockedTokenVault = await newContract(LOCKED_TOKEN_VAULT_CONTRACT_NAME, [DODOToken.options.address, initTime + 86400, 86400, decimalStr("0.1")])
|
||||
|
||||
DODOToken.methods.approve(LockedTokenVault.options.address, MAX_UINT256).send(ctx.sendParam(ctx.Deployer))
|
||||
LockedTokenVault.methods.deposit(decimalStr("10000")).send(ctx.sendParam(ctx.Deployer))
|
||||
}
|
||||
|
||||
describe("Lock DODO Token", () => {
|
||||
|
||||
let snapshotId: string
|
||||
let ctx: DODOContext
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext()
|
||||
await init(ctx);
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId)
|
||||
});
|
||||
|
||||
describe("Lock operations", () => {
|
||||
it("init states", async () => {
|
||||
assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("10000"))
|
||||
await logGas(LockedTokenVault.methods.grant(
|
||||
[u1],
|
||||
[decimalStr("100")]
|
||||
), ctx.sendParam(ctx.Deployer), "grant 1 address")
|
||||
})
|
||||
|
||||
it("grant", async () => {
|
||||
await logGas(LockedTokenVault.methods.grant(
|
||||
[u1, u2, u3],
|
||||
[decimalStr("100"), decimalStr("200"), decimalStr("300")]
|
||||
), ctx.sendParam(ctx.Deployer), "grant 3 address")
|
||||
|
||||
assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("9400"))
|
||||
|
||||
assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100"))
|
||||
assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), decimalStr("200"))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0")
|
||||
|
||||
await ctx.EVM.increaseTime(86400)
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("10")))
|
||||
|
||||
await ctx.EVM.increaseTime(30000)
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("41.25")))
|
||||
})
|
||||
|
||||
it("claim", async () => {
|
||||
await LockedTokenVault.methods.grant(
|
||||
[u1, u2, u3],
|
||||
[decimalStr("100"), decimalStr("200"), decimalStr("300")]
|
||||
).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await ctx.EVM.increaseTime(86400)
|
||||
await LockedTokenVault.methods.claim().send(ctx.sendParam(u1))
|
||||
assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100"))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0")
|
||||
assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("10")))
|
||||
|
||||
await ctx.EVM.increaseTime(30000)
|
||||
await LockedTokenVault.methods.claim().send(ctx.sendParam(u1))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0")
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u1).call(), decimalStr("58.75")))
|
||||
assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("41.25")))
|
||||
|
||||
await LockedTokenVault.methods.claim().send(ctx.sendParam(u2))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0")
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("117.5")))
|
||||
assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("82.5")))
|
||||
})
|
||||
|
||||
it("recall & transfer", async () => {
|
||||
await LockedTokenVault.methods.grant(
|
||||
[u1, u2, u3],
|
||||
[decimalStr("100"), decimalStr("200"), decimalStr("300")]
|
||||
).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
// recall u2
|
||||
await LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer))
|
||||
assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), "0")
|
||||
|
||||
// transfer from u3 to u2
|
||||
await ctx.EVM.increaseTime(86400 + 30000)
|
||||
await LockedTokenVault.methods.transferLockedToken(u2).send(ctx.sendParam(u3))
|
||||
|
||||
await LockedTokenVault.methods.claim().send(ctx.sendParam(u2))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0")
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("176.25")))
|
||||
assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("123.75")))
|
||||
|
||||
// transfer from u2 to u3
|
||||
await ctx.EVM.increaseTime(30000)
|
||||
await LockedTokenVault.methods.transferLockedToken(u3).send(ctx.sendParam(u2))
|
||||
|
||||
await LockedTokenVault.methods.claim().send(ctx.sendParam(u3))
|
||||
assert.equal(await LockedTokenVault.methods.getClaimableBalance(u3).call(), "0")
|
||||
assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u3).call(), decimalStr("82.5")))
|
||||
assert.ok(approxEqual(await DODOToken.methods.balanceOf(u3).call(), decimalStr("93.75")))
|
||||
|
||||
// transfer from u3 to u1
|
||||
await LockedTokenVault.methods.transferLockedToken(u1).send(ctx.sendParam(u3))
|
||||
|
||||
})
|
||||
|
||||
it("withdraw", async () => {
|
||||
await LockedTokenVault.methods.grant(
|
||||
[u1, u2, u3],
|
||||
[decimalStr("100"), decimalStr("200"), decimalStr("300")]
|
||||
).send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
await LockedTokenVault.methods.withdraw(decimalStr("1000")).send(ctx.sendParam(ctx.Deployer))
|
||||
assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("8400"))
|
||||
|
||||
await assert.rejects(
|
||||
LockedTokenVault.methods.withdraw(decimalStr("8500")).send(ctx.sendParam(ctx.Deployer)),
|
||||
/SUB_ERROR/
|
||||
)
|
||||
})
|
||||
|
||||
it("finish distributed", async () => {
|
||||
await LockedTokenVault.methods.grant(
|
||||
[u1, u2, u3],
|
||||
[decimalStr("100"), decimalStr("200"), decimalStr("300")]
|
||||
).send(ctx.sendParam(ctx.Deployer))
|
||||
await LockedTokenVault.methods.finishDistribute().send(ctx.sendParam(ctx.Deployer))
|
||||
|
||||
// can not recall
|
||||
await assert.rejects(
|
||||
LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer)),
|
||||
/DISTRIBUTE FINISHED/
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
function approxEqual(numStr1: string, numStr2: string) {
|
||||
let num1 = new BigNumber(numStr1)
|
||||
let num2 = new BigNumber(numStr2)
|
||||
let ratio = num1.div(num2).minus(1).abs()
|
||||
if (ratio.isLessThan(0.0002)) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -1,553 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import { decimalStr } from './utils/Converter';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let lp: string;
|
||||
let trader: string;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
await ctx.approveDODO(lp);
|
||||
await ctx.approveDODO(trader);
|
||||
|
||||
await ctx.mintTestToken(lp, decimalStr("10"), decimalStr("1000"));
|
||||
await ctx.mintTestToken(trader, decimalStr("10"), decimalStr("1000"));
|
||||
|
||||
await ctx.DODO.methods
|
||||
.depositBaseTo(lp, decimalStr("10"))
|
||||
.send(ctx.sendParam(lp));
|
||||
await ctx.DODO.methods
|
||||
.depositQuoteTo(lp, decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
describe("Trader", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("R goes above ONE", () => {
|
||||
it("buy when R equals ONE", async () => {
|
||||
await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x"), ctx.sendParam(trader), "buy base token when balanced")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("11")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"898581839502056240973"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.001")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0")
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("8.999")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1101418160497943759027"
|
||||
);
|
||||
// price update
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getMidPrice().call(),
|
||||
"102353368821735563400"
|
||||
);
|
||||
});
|
||||
|
||||
it("buy when R is ABOVE ONE", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("130"), "0x"), ctx.sendParam(trader), "buy when R is ABOVE ONE")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("12")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"794367183433412077653"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.002")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0")
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("7.998")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1205632816566587922347"
|
||||
);
|
||||
});
|
||||
|
||||
it("sell when R is ABOVE ONE", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("0.5"), decimalStr("40"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("10.5")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"949280846351657143136"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.001")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"50851561534203512"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("9.499")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1050668302086808653352"
|
||||
);
|
||||
});
|
||||
|
||||
it("sell when R is ABOVE ONE and RStatus back to ONE", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.sellBaseToken("1003002430889317763", decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE and RStatus back to ONE")
|
||||
// R status
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
"9996997569110682237"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"999695745518506168723"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.001")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"101418160497943759"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
"10002002430889317763"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1000202836320995887518"
|
||||
);
|
||||
// target status
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"10002002430889317763"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1000202836320995887518"
|
||||
);
|
||||
});
|
||||
|
||||
it("sell when R is ABOVE ONE and RStatus becomes BELOW ONE", async () => {
|
||||
await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("2"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE and RStatus becomes BELOW ONE [gas cost worst case]")
|
||||
// R status
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2");
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("9")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1098020621600061709144"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.001")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"200038898794388634"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("10.999")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"901779339501143902222"
|
||||
);
|
||||
// target status
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"10002002430889317763"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1000400077797588777268"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("R goes below ONE", () => {
|
||||
it("sell when R equals ONE", async () => {
|
||||
await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell base token when balanced")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("9")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1098617454226610630663"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"0"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"98914196817061816"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("11")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"901283631576572307521"
|
||||
);
|
||||
// price update
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getMidPrice().call(),
|
||||
"97736983274307939149"
|
||||
);
|
||||
});
|
||||
|
||||
it("sell when R is BELOW ONE", async () => {
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("3"), decimalStr("90"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("3"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is BELOW ONE")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("4")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1535961012052716726151"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"0"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"537573733252474148"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("16")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"463501414214030799701"
|
||||
);
|
||||
});
|
||||
|
||||
it("buy when R is BELOW ONE", async () => {
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("0.5"), decimalStr("60"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE")
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("9.5")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1049294316148665165453"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.0005")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"98914196817061816"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("10.4995")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"950606769654517772731"
|
||||
);
|
||||
});
|
||||
|
||||
it("buy when R is BELOW ONE and RStatus back to ONE", async () => {
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.buyBaseToken("997008973080757728", decimalStr("110"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE and RStatus back to ONE")
|
||||
// R status
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
"9997008973080757728"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"999703024198699411500"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"997008973080757"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"98914196817061816"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
"10001994017946161515"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1000198061604483526684"
|
||||
);
|
||||
// target status
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"10001994017946161515"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1000198061604483526684"
|
||||
);
|
||||
});
|
||||
|
||||
it("buy when R is BELOW ONE and RStatus becomes ABOVE ONE", async () => {
|
||||
await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader))
|
||||
await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("2"), decimalStr("220"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE and RStatus becomes ABOVE ONE [gas cost worst case]")
|
||||
// R status
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "1");
|
||||
// trader balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("11")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"897977789597854403796"
|
||||
);
|
||||
// maintainer balances
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
decimalStr("0.002")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(),
|
||||
"98914196817061816"
|
||||
);
|
||||
// dodo balances
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._BASE_BALANCE_().call(),
|
||||
decimalStr("8.998")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._QUOTE_BALANCE_().call(),
|
||||
"1101923296205328534388"
|
||||
);
|
||||
// target status
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(),
|
||||
"10004000000000000000"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(),
|
||||
"1000198061604483526684"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Corner cases", () => {
|
||||
it("buy or sell 0", async () => {
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("0"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("0"), decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
decimalStr("10")
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
decimalStr("1000")
|
||||
);
|
||||
});
|
||||
|
||||
it("buy or sell a tiny amount", async () => {
|
||||
// no precision problem
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken("1", decimalStr("0"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
"9999999999999999999"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1000000000000000000100"
|
||||
);
|
||||
|
||||
// have precision problem, charge 0
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken("1", decimalStr("1"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
"10000000000000000000"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1000000000000000000100"
|
||||
);
|
||||
assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0");
|
||||
|
||||
// no precision problem if trading amount is extremely small
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken("10", decimalStr("1"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(trader).call(),
|
||||
"10000000000000000010"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"999999999999999999100"
|
||||
);
|
||||
});
|
||||
|
||||
it("sell a huge amount of base token", async () => {
|
||||
await ctx.mintTestToken(trader, decimalStr("10000"), "0");
|
||||
await ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("10000"), "0", "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
// nearly drain out quote pool
|
||||
// because the fee donated is greater than remaining quote pool
|
||||
// quote lp earn a considerable profit
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(trader).call(),
|
||||
"1996900220185135480813"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.DODO.methods.getLpQuoteBalance(lp).call(),
|
||||
"4574057156329524019750"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Revert cases", () => {
|
||||
it("price limit", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("1"), decimalStr("100"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/BUY_BASE_COST_TOO_MUCH/
|
||||
);
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.sellBaseToken(decimalStr("1"), decimalStr("100"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/SELL_BASE_RECEIVE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
|
||||
it("base balance limit", async () => {
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("11"), decimalStr("10000"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
|
||||
await ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x")
|
||||
.send(ctx.sendParam(trader));
|
||||
|
||||
await assert.rejects(
|
||||
ctx.DODO.methods
|
||||
.buyBaseToken(decimalStr("11"), decimalStr("10000"), "0x")
|
||||
.send(ctx.sendParam(trader)),
|
||||
/DODO_BASE_BALANCE_NOT_ENOUGH/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { Contract } from 'web3-eth-contract';
|
||||
|
||||
import { DODOContext, getDODOContext } from './utils/DVMContext';
|
||||
import {
|
||||
newContract,
|
||||
UNISWAP_ARBITRAGEUR_CONTRACT_NAME,
|
||||
UNISWAP_CONTRACT_NAME,
|
||||
} from './utils/Contracts';
|
||||
import { decimalStr } from './utils/Converter';
|
||||
import { logGas } from './utils/Log';
|
||||
|
||||
let lp: string;
|
||||
let keeper: string;
|
||||
|
||||
let Uniswap: Contract;
|
||||
let UniswapArbitrageur: Contract;
|
||||
|
||||
let UniswapReverse: Contract;
|
||||
let UniswapArbitrageurReverse: Contract;
|
||||
|
||||
async function init(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
|
||||
lp = ctx.spareAccounts[0];
|
||||
keeper = ctx.spareAccounts[1];
|
||||
await ctx.approveDODO(lp);
|
||||
|
||||
await ctx.mintTestToken(lp, decimalStr("100"), decimalStr("10000"));
|
||||
|
||||
await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp));
|
||||
await ctx.DODO.methods
|
||||
.depositQuote(decimalStr("1000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
|
||||
Uniswap = await newContract(UNISWAP_CONTRACT_NAME);
|
||||
Uniswap.methods
|
||||
.initialize(ctx.BASE.options.address, ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
ctx.BASE.methods
|
||||
.transfer(Uniswap.options.address, decimalStr("10"))
|
||||
.send(ctx.sendParam(lp));
|
||||
ctx.QUOTE.methods
|
||||
.transfer(Uniswap.options.address, decimalStr("2000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
Uniswap.methods.sync().send(ctx.sendParam(lp));
|
||||
|
||||
UniswapArbitrageur = await newContract(UNISWAP_ARBITRAGEUR_CONTRACT_NAME, [
|
||||
Uniswap.options.address,
|
||||
ctx.DODO.options.address,
|
||||
]);
|
||||
|
||||
UniswapReverse = await newContract(UNISWAP_CONTRACT_NAME);
|
||||
UniswapReverse.methods
|
||||
.initialize(ctx.BASE.options.address, ctx.QUOTE.options.address)
|
||||
.send(ctx.sendParam(ctx.Deployer));
|
||||
ctx.BASE.methods
|
||||
.transfer(UniswapReverse.options.address, decimalStr("10"))
|
||||
.send(ctx.sendParam(lp));
|
||||
ctx.QUOTE.methods
|
||||
.transfer(UniswapReverse.options.address, decimalStr("2000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
UniswapReverse.methods.sync().send(ctx.sendParam(lp));
|
||||
|
||||
UniswapArbitrageurReverse = await newContract(
|
||||
UNISWAP_ARBITRAGEUR_CONTRACT_NAME,
|
||||
[UniswapReverse.options.address, ctx.DODO.options.address]
|
||||
);
|
||||
}
|
||||
|
||||
describe("Uniswap Arbitrageur", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
ctx = await getDODOContext();
|
||||
await init(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("arbitrage with not reverse pair", () => {
|
||||
it("buy at dodo", async () => {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
// dodo price 100 uniswap price 200
|
||||
// buy at dodo
|
||||
<<<<<<< Updated upstream
|
||||
await logGas(
|
||||
UniswapArbitrageur.methods.executeBuyArbitrage(decimalStr("1")),
|
||||
ctx.sendParam(keeper),
|
||||
"arbitrage buy at dodo not reverse"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(keeper).call(),
|
||||
"79836384956601695518"
|
||||
);
|
||||
});
|
||||
=======
|
||||
logGas(await UniswapArbitrageur.methods.executeBuyArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage buy at dodo not reverse")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518")
|
||||
})
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
it("sell at dodo", async () => {
|
||||
await ctx.setOraclePrice(decimalStr("300"));
|
||||
// dodo price 300 uniswap price 200
|
||||
// sell at dodo
|
||||
<<<<<<< Updated upstream
|
||||
await logGas(
|
||||
UniswapArbitrageur.methods.executeSellArbitrage(decimalStr("1")),
|
||||
ctx.sendParam(keeper),
|
||||
"arbitrage sell at dodo not reverse"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(keeper).call(),
|
||||
"252761069524143743"
|
||||
);
|
||||
});
|
||||
});
|
||||
=======
|
||||
logGas(await UniswapArbitrageur.methods.executeSellArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage sell at dodo not reverse")
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743")
|
||||
})
|
||||
})
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
describe("arbitrage with reverse pair", () => {
|
||||
it("buy at dodo", async () => {
|
||||
await ctx.setOraclePrice(decimalStr("100"));
|
||||
// dodo price 100 uniswap price 200
|
||||
// buy at dodo
|
||||
<<<<<<< Updated upstream
|
||||
await logGas(
|
||||
UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")),
|
||||
ctx.sendParam(keeper),
|
||||
"arbitrage buy at dodo reverse"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.QUOTE.methods.balanceOf(keeper).call(),
|
||||
"79836384956601695518"
|
||||
);
|
||||
});
|
||||
=======
|
||||
logGas(await UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage buy at dodo reverse")
|
||||
assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518")
|
||||
})
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
it("sell at dodo", async () => {
|
||||
await ctx.setOraclePrice(decimalStr("300"));
|
||||
// dodo price 300 uniswap price 200
|
||||
// sell at dodo
|
||||
<<<<<<< Updated upstream
|
||||
await logGas(
|
||||
UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")),
|
||||
ctx.sendParam(keeper),
|
||||
"arbitrage sell at dodo reverse"
|
||||
);
|
||||
assert.equal(
|
||||
await ctx.BASE.methods.balanceOf(keeper).call(),
|
||||
"252761069524143743"
|
||||
);
|
||||
});
|
||||
});
|
||||
=======
|
||||
logGas(await UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage sell at dodo reverse")
|
||||
assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743")
|
||||
})
|
||||
})
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
describe("revert cases", () => {
|
||||
it("price not match", async () => {
|
||||
await ctx.setOraclePrice(decimalStr("200"));
|
||||
await assert.rejects(
|
||||
UniswapArbitrageurReverse.methods
|
||||
.executeBuyArbitrage(decimalStr("1"))
|
||||
.send(ctx.sendParam(keeper)),
|
||||
/NOT_PROFITABLE/
|
||||
);
|
||||
await assert.rejects(
|
||||
UniswapArbitrageurReverse.methods
|
||||
.executeSellArbitrage(decimalStr("1"))
|
||||
.send(ctx.sendParam(keeper)),
|
||||
/NOT_PROFITABLE/
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 DODO ZOO.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
*/
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { DODOContext, getDODOContext } from '../utils-v1/ProxyContextV1';
|
||||
import { decimalStr, MAX_UINT256, fromWei, mweiStr } from '../utils-v1/Converter';
|
||||
import { logGas } from '../utils-v1/Log';
|
||||
import * as contracts from '../utils-v1/Contracts';
|
||||
import { assert } from 'chai';
|
||||
|
||||
let lp: string;
|
||||
let trader: string;
|
||||
|
||||
async function initDODO_USDT(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(ctx.DODO_USDT_ORACLE, mweiStr("0.1"));
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
|
||||
let DODO = ctx.DODO;
|
||||
let USDT = ctx.USDT;
|
||||
let DODO_USDT = ctx.DODO_USDT;
|
||||
await ctx.approvePair(DODO, USDT, DODO_USDT.options.address, lp);
|
||||
await ctx.approvePair(DODO, USDT, DODO_USDT.options.address, trader);
|
||||
|
||||
await ctx.mintToken(DODO, USDT, lp, decimalStr("10000000"), mweiStr("1000000"));
|
||||
|
||||
await DODO_USDT.methods
|
||||
.depositBaseTo(lp, decimalStr("10000000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
await DODO_USDT.methods
|
||||
.depositQuoteTo(lp, mweiStr("1000000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
async function initUSDT_USDC(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(ctx.USDT_USDC_ORACLE, decimalStr("1"));
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
|
||||
let USDT = ctx.USDT;
|
||||
let USDC = ctx.USDC;
|
||||
let USDT_USDC = ctx.USDT_USDC;
|
||||
|
||||
await ctx.approvePair(USDT, USDC, USDT_USDC.options.address, lp);
|
||||
await ctx.mintToken(USDT, USDC, lp, mweiStr("1000000"), mweiStr("1000000"));
|
||||
|
||||
await USDT_USDC.methods
|
||||
.depositBaseTo(lp, mweiStr("1000000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
await USDT_USDC.methods
|
||||
.depositQuoteTo(lp, mweiStr("1000000"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
|
||||
async function initWETH_USDC(ctx: DODOContext): Promise<void> {
|
||||
await ctx.setOraclePrice(ctx.WETH_USDC_ORACLE, mweiStr("450"));
|
||||
lp = ctx.spareAccounts[0];
|
||||
trader = ctx.spareAccounts[1];
|
||||
|
||||
let WETH = ctx.WETH;
|
||||
let USDC = ctx.USDC;
|
||||
let WETH_USDC = ctx.WETH_USDC;
|
||||
|
||||
await ctx.approvePair(WETH, USDC, WETH_USDC.options.address, lp);
|
||||
await ctx.mintToken(null, USDC, lp, decimalStr("0"), mweiStr("3600"));
|
||||
await WETH.methods.deposit().send(ctx.sendParam(lp, '8'));
|
||||
|
||||
await WETH_USDC.methods
|
||||
.depositBaseTo(lp, decimalStr("8"))
|
||||
.send(ctx.sendParam(lp));
|
||||
await WETH_USDC.methods
|
||||
.depositQuoteTo(lp, mweiStr("3600"))
|
||||
.send(ctx.sendParam(lp));
|
||||
}
|
||||
|
||||
async function initIncentive(ctx: DODOContext): Promise<void> {
|
||||
var blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer));
|
||||
await ctx.mintToken(ctx.DODO, null, ctx.DODOIncentive.options.address, decimalStr("10000"), mweiStr("0"));
|
||||
}
|
||||
|
||||
//mock sdk logic
|
||||
async function calcRoute(ctx: DODOContext, fromTokenAmount: string, slippage: number, routes: any[], pairs: any[], isIncentive: boolean) {
|
||||
let tmpDirections: number[] = []
|
||||
let strDirections: string = ''
|
||||
let dodoPairs: string[] = []
|
||||
|
||||
for (let i = 0; i < pairs.length; i++) {
|
||||
let curPair = pairs[i]
|
||||
dodoPairs.push(curPair.pair)
|
||||
if (routes[i].address == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') {
|
||||
tmpDirections[i] = 0;
|
||||
} else if (curPair.base === routes[i].address) {
|
||||
tmpDirections[i] = 0;
|
||||
} else {
|
||||
tmpDirections[i] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
var [returmAmount,] = await ctx.DODOSwapCalcHelper.methods.calcReturnAmountV1(
|
||||
fromTokenAmount,
|
||||
dodoPairs,
|
||||
tmpDirections,
|
||||
).call();
|
||||
// console.log("returnAmount:", returmAmount)
|
||||
// console.log("localAmount:", swapAmount)
|
||||
// console.log("midPrices:", midPrices)
|
||||
|
||||
|
||||
let toAmount = new BigNumber(returmAmount).multipliedBy(1 - slippage).toFixed(0, BigNumber.ROUND_DOWN)
|
||||
let deadline = Math.floor(new Date().getTime() / 1000 + 60 * 10);
|
||||
|
||||
for (let i = tmpDirections.length - 1; i >= 0; i--) {
|
||||
strDirections += tmpDirections[i].toString()
|
||||
}
|
||||
|
||||
return ctx.DODOV1Proxy02.methods.dodoSwapV1(
|
||||
routes[0].address,
|
||||
routes[routes.length - 1].address,
|
||||
fromTokenAmount,
|
||||
toAmount,
|
||||
dodoPairs,
|
||||
parseInt(strDirections, 2),
|
||||
isIncentive,
|
||||
deadline
|
||||
)
|
||||
}
|
||||
|
||||
describe("Trader", () => {
|
||||
let snapshotId: string;
|
||||
let ctx: DODOContext;
|
||||
|
||||
before(async () => {
|
||||
let ETH = await contracts.newContract(
|
||||
contracts.WETH_CONTRACT_NAME
|
||||
);
|
||||
ctx = await getDODOContext(ETH.options.address);
|
||||
await initDODO_USDT(ctx);
|
||||
await initUSDT_USDC(ctx);
|
||||
await initWETH_USDC(ctx);
|
||||
await initIncentive(ctx);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
snapshotId = await ctx.EVM.snapshot();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await ctx.EVM.reset(snapshotId);
|
||||
});
|
||||
|
||||
describe("route calc with incentive test", () => {
|
||||
it("incentive-switch with trade", async () => {
|
||||
await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer));
|
||||
var totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
var blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("Init - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum);
|
||||
|
||||
//Aim to increase block
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("Close BlockNumber:", blockNum + 1)
|
||||
await ctx.DODOIncentive.methods.switchIncentive(0).send(ctx.sendParam(ctx.Deployer));
|
||||
totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("Close incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum)
|
||||
//Aim to increase block
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer));
|
||||
console.log("Open BlockNumber:", blockNum + 1)
|
||||
//Aim to increase block
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer));
|
||||
totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("End incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum)
|
||||
assert(totalReward, decimalStr("100"));
|
||||
});
|
||||
|
||||
it("incentive-changeBoost with trade", async () => {
|
||||
await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer));
|
||||
var totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
var blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("Init - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum);
|
||||
|
||||
//Aim to increase block
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("Change BlockNumber:", blockNum + 1)
|
||||
await ctx.DODOIncentive.methods.changePerReward(decimalStr("20")).send(ctx.sendParam(ctx.Deployer));
|
||||
totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("change incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum)
|
||||
|
||||
//Aim to increase block
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0"));
|
||||
await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer));
|
||||
totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
blockNum = await ctx.Web3.eth.getBlockNumber();
|
||||
console.log("End incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum)
|
||||
assert(totalReward, decimalStr("140"));
|
||||
});
|
||||
|
||||
it("directly swap with incentive", async () => {
|
||||
await ctx.mintToken(ctx.DODO, ctx.USDT, trader, decimalStr("1000"), mweiStr("0"));
|
||||
var b_DODO = await ctx.DODO.methods.balanceOf(trader).call()
|
||||
var b_USDT = await ctx.USDT.methods.balanceOf(trader).call()
|
||||
console.log("Before DODO:" + fromWei(b_DODO, 'ether') + "; USDT:" + fromWei(b_USDT, 'mwei'));
|
||||
|
||||
var b_totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
var b_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
console.log("Before Total Reward:" + fromWei(b_totalReward, 'ether') + "; Total distribution:" + fromWei(b_totalDistribution, 'ether'))
|
||||
|
||||
//approve DODO entry
|
||||
await ctx.DODO.methods.approve(ctx.DODOApprove.options.address, MAX_UINT256).send(ctx.sendParam(trader))
|
||||
//set route path
|
||||
var routes = [{
|
||||
address: ctx.DODO.options.address,
|
||||
decimals: 18
|
||||
},
|
||||
{
|
||||
address: ctx.USDT.options.address,
|
||||
decimals: 6
|
||||
}];
|
||||
|
||||
var pairs = [{
|
||||
pair: ctx.DODO_USDT.options.address,
|
||||
base: ctx.DODO.options.address,
|
||||
pairContract: ctx.DODO_USDT
|
||||
}];
|
||||
await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, false), ctx.sendParam(trader), "directly swap without incentive first")
|
||||
await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, false), ctx.sendParam(trader), "directly swap without incentive second")
|
||||
var a_DODO = await ctx.DODO.methods.balanceOf(trader).call()
|
||||
var a_USDT = await ctx.USDT.methods.balanceOf(trader).call()
|
||||
console.log("After No Incentive DODO:" + fromWei(a_DODO, 'ether') + "; USDT:" + fromWei(a_USDT, 'mwei'));
|
||||
|
||||
await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, true), ctx.sendParam(trader), "directly swap with incentive first")
|
||||
await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, true), ctx.sendParam(trader), "directly swap with incentive second")
|
||||
|
||||
var a_totalReward = await ctx.DODOIncentive.methods.totalReward().call();
|
||||
var a_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call();
|
||||
console.log("After Total Reward:" + fromWei(a_totalReward, 'ether') + "; Total distribution:" + fromWei(a_totalDistribution, 'ether'))
|
||||
|
||||
a_DODO = await ctx.DODO.methods.balanceOf(trader).call()
|
||||
a_USDT = await ctx.USDT.methods.balanceOf(trader).call()
|
||||
console.log("After Incentive DODO:" + fromWei(a_DODO, 'ether') + "; USDT:" + fromWei(a_USDT, 'mwei'));
|
||||
assert(a_DODO, decimalStr("961.493"));
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -256,7 +256,7 @@ export class DODOContext {
|
||||
await this.DODOV1Proxy02.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer));
|
||||
await this.DODOIncentive.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer));
|
||||
|
||||
await this.DODOApprove.methods.init(this.Deployer,this.DODOV1Proxy02.options.address).send(this.sendParam(this.Deployer));
|
||||
await this.DODOApprove.methods.init(this.Deployer, this.DODOV1Proxy01.options.address).send(this.sendParam(this.Deployer));
|
||||
await this.DODOIncentive.methods.changeDODOProxy(this.DODOV1Proxy02.options.address).send(this.sendParam(this.Deployer));
|
||||
|
||||
this.DODOSwapCalcHelper = await contracts.newContract(
|
||||
|
||||
Reference in New Issue
Block a user