From 1fc5b938652b3fd3ea58e1ed6f404971a85de87c Mon Sep 17 00:00:00 2001 From: Michael Zhou Date: Tue, 8 Sep 2020 20:25:59 +0800 Subject: [PATCH] Fix tests Use the new logGas. --- test/LiquidityProvider.test.ts | 1014 ++++++++++++++++++++++--------- test/Trader.test.ts | 662 +++++++++++++++----- test/UniswapArbitrageur.test.ts | 180 ++++-- 3 files changed, 1362 insertions(+), 494 deletions(-) diff --git a/test/LiquidityProvider.test.ts b/test/LiquidityProvider.test.ts index fb149e2..6ba239b 100644 --- a/test/LiquidityProvider.test.ts +++ b/test/LiquidityProvider.test.ts @@ -5,453 +5,921 @@ */ +import * as assert from 'assert'; + import { DODOContext, getDODOContext } from './utils/Context'; import { decimalStr } from './utils/Converter'; import { logGas } from './utils/Log'; -import * as assert from "assert" -let lp1: string -let lp2: string -let trader: string +let lp1: string; +let lp2: string; +let trader: string; async function init(ctx: DODOContext): Promise { - 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) + 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 + let snapshotId: string; + let ctx: DODOContext; before(async () => { - ctx = await getDODOContext() + ctx = await getDODOContext(); await init(ctx); - }) + }); beforeEach(async () => { snapshotId = await ctx.EVM.snapshot(); }); afterEach(async () => { - await ctx.EVM.reset(snapshotId) + 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")) + assert.equal( + await ctx.DODO.methods.getLpBaseBalance(lp1).call(), + decimalStr("0") + ); + assert.equal( + await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), + decimalStr("0") + ); - logGas(await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)), "deposit base") - assert.equal(await ctx.BASE.methods.balanceOf(lp1).call(), decimalStr("90")) - logGas(await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1)), "deposit quote") - assert.equal(await ctx.QUOTE.methods.balanceOf(lp1).call(), decimalStr("9000")) + 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")) + 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)) + 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")) + 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 + .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")) - }) - }) + 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)) + 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")) + 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)) + 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(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.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") - }) + 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)) + 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") + 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 + .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")) - }) - }) + 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)) + 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") + 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)) + 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(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.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") - }) + 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)) + 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") + 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 + .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")) - }) - }) + 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.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") + 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")) + 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") - }) + 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.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")) + 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")) + 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")) - }) - - }) + 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.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.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)) + 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")) - }) - }) + 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)) + 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")) - }) + 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)) + 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")) - }) - }) + 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)) + 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") + 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)) + await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2)); - assert.equal(await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(), "1103903610832497493") - }) + 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 + .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)) + 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") - }) + 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.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)) + 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") + 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") - }) + 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.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)) + 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") + 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") - }) + 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.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)) + 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") + 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") - }) + 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)) + 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") + assert.equal( + await ctx.DODO.methods.getLpBaseBalance(lp1).call(), + "10010841132009222923" + ); - await ctx.DODO.methods.depositBase(decimalStr("5")).send(ctx.sendParam(lp2)) + 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") + 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)) + 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") - }) - }) + 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 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 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)), + 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 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)), + 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 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)), + 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 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)), + 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 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)), + 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 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)), + 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)), + 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)), + ctx.DODO.methods + .withdrawQuote(decimalStr("1")) + .send(ctx.sendParam(lp1)), /NO_QUOTE_LP/ - ) - }) - }) - -}) \ No newline at end of file + ); + }); + }); +}); diff --git a/test/Trader.test.ts b/test/Trader.test.ts index 9046248..506aef4 100644 --- a/test/Trader.test.ts +++ b/test/Trader.test.ts @@ -5,277 +5,621 @@ */ +import * as assert from 'assert'; + import { DODOContext, getDODOContext } from './utils/Context'; import { decimalStr } from './utils/Converter'; import { logGas } from './utils/Log'; -import * as assert from "assert" -let lp: string -let trader: string +let lp: string; +let trader: string; async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")) + await ctx.setOraclePrice(decimalStr("100")); - lp = ctx.spareAccounts[0] - trader = ctx.spareAccounts[1] - await ctx.approveDODO(lp) - await ctx.approveDODO(trader) + 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.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)) + 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 + let snapshotId: string; + let ctx: DODOContext; before(async () => { - ctx = await getDODOContext() + ctx = await getDODOContext(); await init(ctx); - }) + }); beforeEach(async () => { snapshotId = await ctx.EVM.snapshot(); }); afterEach(async () => { - await ctx.EVM.reset(snapshotId) + await ctx.EVM.reset(snapshotId); }); describe("R goes above ONE", () => { it("buy when R equals ONE", async () => { - logGas(await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)), "buy base token when balanced") + 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") + 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")) + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("130"), "0x").send(ctx.sendParam(trader)), "buy when R is ABOVE ONE") + 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") + 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")) + 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") - }) + 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)) - logGas(await ctx.DODO.methods.sellBaseToken(decimalStr("0.5"), decimalStr("40"), "0x").send(ctx.sendParam(trader)), "sell when R is ABOVE ONE") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.sellBaseToken("1003002430889317763", decimalStr("90"), "0x").send(ctx.sendParam(trader)), "sell when R is ABOVE ONE and RStatus back to ONE") + 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") + 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") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.sellBaseToken(decimalStr("2"), decimalStr("90"), "0x").send(ctx.sendParam(trader)), "sell when R is ABOVE ONE and RStatus becomes BELOW ONE [gas cost worst case]") + 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") + 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") + 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") + 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") + 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") - }) - }) + 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 () => { - logGas(await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader)), "sell base token when balanced") + 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") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.sellBaseToken(decimalStr("3"), decimalStr("90"), "0x").send(ctx.sendParam(trader)), "sell when R is BELOW ONE") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.buyBaseToken(decimalStr("0.5"), decimalStr("60"), "0x").send(ctx.sendParam(trader)), "buy when R is BELOW ONE") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.buyBaseToken("997008973080757728", decimalStr("110"), "0x").send(ctx.sendParam(trader)), "buy when R is BELOW ONE and RStatus back to ONE") + 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") + 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") + 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") + 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") + 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") - }) + 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)) - logGas(await ctx.DODO.methods.buyBaseToken(decimalStr("2"), decimalStr("220"), "0x").send(ctx.sendParam(trader)), "buy when R is BELOW ONE and RStatus becomes ABOVE ONE [gas cost worst case]") + 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") + 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") + 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") + 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") + 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") - }) - }) + 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 + .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")) - }) + 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") + 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") + 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") - }) + 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)) + 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") - }) - }) + 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)), + 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)), + 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)), + 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 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)), + ctx.DODO.methods + .buyBaseToken(decimalStr("11"), decimalStr("10000"), "0x") + .send(ctx.sendParam(trader)), /DODO_BASE_BALANCE_NOT_ENOUGH/ - ) - }) - }) -}) \ No newline at end of file + ); + }); + }); +}); diff --git a/test/UniswapArbitrageur.test.ts b/test/UniswapArbitrageur.test.ts index b7c53c8..1df1df3 100644 --- a/test/UniswapArbitrageur.test.ts +++ b/test/UniswapArbitrageur.test.ts @@ -5,116 +5,172 @@ */ -import { DODOContext, getDODOContext } from './utils/Context'; -import { decimalStr } from './utils/Converter'; -import { logGas } from './utils/Log'; -import * as assert from "assert" -import { newContract, UNISWAP_CONTRACT_NAME, UNISWAP_ARBITRAGEUR_CONTRACT_NAME } from './utils/Contracts'; +import * as assert from 'assert'; import { Contract } from 'web3-eth-contract'; -let lp: string -let keeper: string +import { DODOContext, getDODOContext } from './utils/Context'; +import { + newContract, + UNISWAP_ARBITRAGEUR_CONTRACT_NAME, + UNISWAP_CONTRACT_NAME, +} from './utils/Contracts'; +import { decimalStr } from './utils/Converter'; +import { logGas } from './utils/Log'; -let Uniswap: Contract -let UniswapArbitrageur: Contract +let lp: string; +let keeper: string; -let UniswapReverse: Contract -let UniswapArbitrageurReverse: Contract +let Uniswap: Contract; +let UniswapArbitrageur: Contract; + +let UniswapReverse: Contract; +let UniswapArbitrageurReverse: Contract; async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")) + await ctx.setOraclePrice(decimalStr("100")); - lp = ctx.spareAccounts[0] - keeper = ctx.spareAccounts[1] - await ctx.approveDODO(lp) + lp = ctx.spareAccounts[0]; + keeper = ctx.spareAccounts[1]; + await ctx.approveDODO(lp); - await ctx.mintTestToken(lp, decimalStr("100"), decimalStr("10000")) + 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)) + 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)) + 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]) + 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)) + 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]) + UniswapArbitrageurReverse = await newContract( + UNISWAP_ARBITRAGEUR_CONTRACT_NAME, + [UniswapReverse.options.address, ctx.DODO.options.address] + ); } describe("Uniswap Arbitrageur", () => { - - let snapshotId: string - let ctx: DODOContext + let snapshotId: string; + let ctx: DODOContext; before(async () => { - ctx = await getDODOContext() + ctx = await getDODOContext(); await init(ctx); - }) + }); beforeEach(async () => { snapshotId = await ctx.EVM.snapshot(); }); afterEach(async () => { - await ctx.EVM.reset(snapshotId) + await ctx.EVM.reset(snapshotId); }); describe("arbitrage with not reverse pair", () => { it("buy at dodo", async () => { - await ctx.setOraclePrice(decimalStr("100")) + await ctx.setOraclePrice(decimalStr("100")); // dodo price 100 uniswap price 200 // buy at dodo - logGas(await UniswapArbitrageur.methods.executeBuyArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), "arbitrage buy at dodo not reverse") - assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518") - }) + 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" + ); + }); it("sell at dodo", async () => { - await ctx.setOraclePrice(decimalStr("300")) + await ctx.setOraclePrice(decimalStr("300")); // dodo price 300 uniswap price 200 // sell at dodo - logGas(await UniswapArbitrageur.methods.executeSellArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), "arbitrage sell at dodo not reverse") - assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743") - }) - }) + 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" + ); + }); + }); describe("arbitrage with reverse pair", () => { it("buy at dodo", async () => { - await ctx.setOraclePrice(decimalStr("100")) + await ctx.setOraclePrice(decimalStr("100")); // dodo price 100 uniswap price 200 // buy at dodo - logGas(await UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), "arbitrage buy at dodo reverse") - assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518") - }) + 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" + ); + }); it("sell at dodo", async () => { - await ctx.setOraclePrice(decimalStr("300")) + await ctx.setOraclePrice(decimalStr("300")); // dodo price 300 uniswap price 200 // sell at dodo - logGas(await UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), "arbitrage sell at dodo reverse") - assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743") - }) - }) + 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" + ); + }); + }); describe("revert cases", () => { it("price not match", async () => { - await ctx.setOraclePrice(decimalStr("200")) + await ctx.setOraclePrice(decimalStr("200")); await assert.rejects( - UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), + UniswapArbitrageurReverse.methods + .executeBuyArbitrage(decimalStr("1")) + .send(ctx.sendParam(keeper)), /NOT_PROFITABLE/ - ) + ); await assert.rejects( - UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")).send(ctx.sendParam(keeper)), + UniswapArbitrageurReverse.methods + .executeSellArbitrage(decimalStr("1")) + .send(ctx.sendParam(keeper)), /NOT_PROFITABLE/ - ) - }) - }) -}) \ No newline at end of file + ); + }); + }); +});