diff --git a/contracts/dodo.sol b/contracts/dodo.sol index 81be5dd..8e63036 100644 --- a/contracts/dodo.sol +++ b/contracts/dodo.sol @@ -16,6 +16,7 @@ import {LiquidityProvider} from "./impl/LiquidityProvider.sol"; import {Admin} from "./impl/Admin.sol"; import {DODOLpToken} from "./impl/DODOLpToken.sol"; + /** * @title DODO * @author DODO Breeder @@ -48,11 +49,18 @@ contract DODO is Admin, Trader, LiquidityProvider { _QUOTE_TOKEN_ = quoteToken; _ORACLE_ = oracle; - _DEPOSIT_BASE_ALLOWED_ = true; - _DEPOSIT_QUOTE_ALLOWED_ = true; - _TRADE_ALLOWED_ = true; + _DEPOSIT_BASE_ALLOWED_ = false; + _DEPOSIT_QUOTE_ALLOWED_ = false; + _TRADE_ALLOWED_ = false; _GAS_PRICE_LIMIT_ = gasPriceLimit; + // Advanced controls are disabled by default + _BUYING_ALLOWED_ = true; + _SELLING_ALLOWED_ = true; + uint256 MAX_INT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + _BASE_BALANCE_LIMIT_ = MAX_INT; + _QUOTE_BALANCE_LIMIT_ = MAX_INT; + _LP_FEE_RATE_ = lpFeeRate; _MT_FEE_RATE_ = mtFeeRate; _K_ = k; diff --git a/contracts/impl/Admin.sol b/contracts/impl/Admin.sol index fd89052..2e5edf7 100644 --- a/contracts/impl/Admin.sol +++ b/contracts/impl/Admin.sol @@ -10,6 +10,7 @@ pragma experimental ABIEncoderV2; import {Storage} from "./Storage.sol"; + /** * @title Admin * @author DODO Breeder @@ -92,4 +93,30 @@ contract Admin is Storage { function enableBaseDeposit() external onlyOwner notClosed { _DEPOSIT_BASE_ALLOWED_ = true; } + + // ============ Advanced Control Functions ============ + + function disableBuying() external onlySupervisorOrOwner { + _BUYING_ALLOWED_ = false; + } + + function enableBuying() external onlyOwner notClosed { + _BUYING_ALLOWED_ = true; + } + + function disableSelling() external onlySupervisorOrOwner { + _SELLING_ALLOWED_ = false; + } + + function enableSelling() external onlyOwner notClosed { + _SELLING_ALLOWED_ = true; + } + + function setBaseBalanceLimit(uint256 newBaseBalanceLimit) external onlyOwner notClosed { + _BASE_BALANCE_LIMIT_ = newBaseBalanceLimit; + } + + function setQuoteBalanceLimit(uint256 newQuoteBalanceLimit) external onlyOwner notClosed { + _QUOTE_BALANCE_LIMIT_ = newQuoteBalanceLimit; + } } diff --git a/contracts/impl/Settlement.sol b/contracts/impl/Settlement.sol index 087a627..d301a5b 100644 --- a/contracts/impl/Settlement.sol +++ b/contracts/impl/Settlement.sol @@ -15,6 +15,7 @@ import {Types} from "../lib/Types.sol"; import {IERC20} from "../intf/IERC20.sol"; import {Storage} from "./Storage.sol"; + /** * @title Settlement * @author DODO Breeder @@ -34,11 +35,16 @@ contract Settlement is Storage { // ============ Assets IN/OUT Functions ============ function _baseTokenTransferIn(address from, uint256 amount) internal { + require(_BASE_BALANCE_.add(amount) <= _BASE_BALANCE_LIMIT_, "BASE_BALANCE_LIMIT_EXCEEDED"); IERC20(_BASE_TOKEN_).safeTransferFrom(from, address(this), amount); _BASE_BALANCE_ = _BASE_BALANCE_.add(amount); } function _quoteTokenTransferIn(address from, uint256 amount) internal { + require( + _QUOTE_BALANCE_.add(amount) <= _QUOTE_BALANCE_LIMIT_, + "QUOTE_BALANCE_LIMIT_EXCEEDED" + ); IERC20(_QUOTE_TOKEN_).safeTransferFrom(from, address(this), amount); _QUOTE_BALANCE_ = _QUOTE_BALANCE_.add(amount); } diff --git a/contracts/impl/Storage.sol b/contracts/impl/Storage.sol index dd34d3e..7828bde 100644 --- a/contracts/impl/Storage.sol +++ b/contracts/impl/Storage.sol @@ -16,6 +16,7 @@ import {IOracle} from "../intf/IOracle.sol"; import {IDODOLpToken} from "../intf/IDODOLpToken.sol"; import {Types} from "../lib/Types.sol"; + /** * @title Storage * @author DODO Breeder @@ -34,6 +35,12 @@ contract Storage is InitializableOwnable, ReentrancyGuard { bool public _TRADE_ALLOWED_; uint256 public _GAS_PRICE_LIMIT_; + // ============ Advanced Controls ============ + bool public _BUYING_ALLOWED_; + bool public _SELLING_ALLOWED_; + uint256 public _BASE_BALANCE_LIMIT_; + uint256 public _QUOTE_BALANCE_LIMIT_; + // ============ Core Address ============ address public _SUPERVISOR_; // could freeze system in emergency @@ -106,6 +113,6 @@ contract Storage is InitializableOwnable, ReentrancyGuard { // ============ Version Control ============ function version() external pure returns (uint256) { - return 100; // 1.0.0 + return 101; // 1.0.1 } } diff --git a/contracts/impl/Trader.sol b/contracts/impl/Trader.sol index c18d4cf..36d00d9 100644 --- a/contracts/impl/Trader.sol +++ b/contracts/impl/Trader.sol @@ -16,6 +16,7 @@ import {Storage} from "./Storage.sol"; import {Pricing} from "./Pricing.sol"; import {Settlement} from "./Settlement.sol"; + /** * @title Trader * @author DODO Breeder @@ -40,6 +41,16 @@ contract Trader is Storage, Pricing, Settlement { _; } + modifier buyingAllowed() { + require(_BUYING_ALLOWED_, "BUYING_NOT_ALLOWED"); + _; + } + + modifier sellingAllowed() { + require(_SELLING_ALLOWED_, "SELLING_NOT_ALLOWED"); + _; + } + modifier gasPriceLimit() { require(tx.gasprice <= _GAS_PRICE_LIMIT_, "GAS_PRICE_EXCEED"); _; @@ -51,7 +62,7 @@ contract Trader is Storage, Pricing, Settlement { uint256 amount, uint256 minReceiveQuote, bytes calldata data - ) external tradeAllowed gasPriceLimit preventReentrant returns (uint256) { + ) external tradeAllowed sellingAllowed gasPriceLimit preventReentrant returns (uint256) { // query price ( uint256 receiveQuote, @@ -95,7 +106,7 @@ contract Trader is Storage, Pricing, Settlement { uint256 amount, uint256 maxPayQuote, bytes calldata data - ) external tradeAllowed gasPriceLimit preventReentrant returns (uint256) { + ) external tradeAllowed buyingAllowed gasPriceLimit preventReentrant returns (uint256) { // query price ( uint256 payQuote, diff --git a/test/Admin.test.ts b/test/Admin.test.ts index 3b95c64..49fda32 100644 --- a/test/Admin.test.ts +++ b/test/Admin.test.ts @@ -5,336 +5,606 @@ */ +import * as assert from 'assert'; + import { DODOContext, getDODOContext } from './utils/Context'; import { decimalStr } from './utils/Converter'; -// import BigNumber from "bignumber.js"; -import * as assert from "assert" -let lp1: string -let lp2: string -let trader: string -let tempAccount: string +let lp1: string; +let lp2: string; +let trader: string; +let tempAccount: string; async function init(ctx: DODOContext): Promise { - 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) + 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 + 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("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) - }) + 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) - }) + 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) - }) + 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")) - }) + 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")) - }) + 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")) - }) + 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")) - }) - }) + 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 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 + .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 ctx.DODO.methods + .disableQuoteDeposit() + .send(ctx.sendParam(ctx.Supervisor)); await assert.rejects( - ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1)), + 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 + .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 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)), + 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")) - }) + 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)), + 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)), + 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 + .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 + .finalSettlement() + .send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)) - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)) - await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)) + await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); + await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)); + await ctx.DODO.methods.withdrawAllQuote().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")) - }) + 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 + .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 + .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("90")) - assert.equal(await ctx.QUOTE.methods.balanceOf(lp1).call(), "9551951805416248746110") - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)) - await ctx.DODO.methods.withdrawAllQuote().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") - }) + await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); + assert.equal( + await ctx.BASE.methods.balanceOf(lp1).call(), + decimalStr("90") + ); + assert.equal( + await ctx.QUOTE.methods.balanceOf(lp1).call(), + "9551951805416248746110" + ); + await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)); + await ctx.DODO.methods.withdrawAllQuote().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 + .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 + .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("95")) - assert.equal(await ctx.QUOTE.methods.balanceOf(lp1).call(), decimalStr("9000")) - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)) - await ctx.DODO.methods.withdrawAllQuote().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") - }) + await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); + assert.equal( + await ctx.BASE.methods.balanceOf(lp1).call(), + decimalStr("95") + ); + assert.equal( + await ctx.QUOTE.methods.balanceOf(lp1).call(), + decimalStr("9000") + ); + await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)); + await ctx.DODO.methods.withdrawAllQuote().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 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 + .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 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 ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp2)) + 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 + .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)) + 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") + 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.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)) + 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") - }) - }) + 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 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)), + 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)), + 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")) - }) + ); + 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 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)), + 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")) - }) - }) + ); + 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)), + 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)), + 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)), + 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)), + ctx.DODO.methods + .setMaintainerFeeRate(decimalStr("0.998")) + .send(ctx.sendParam(ctx.Deployer)), /FEE_RATE>=1/ - ) - }) - }) -}) \ No newline at end of file + ); + }); + }); +}); diff --git a/test/DODOEthProxyAsBase.test.ts b/test/DODOEthProxyAsBase.test.ts index e72babc..85d674b 100644 --- a/test/DODOEthProxyAsBase.test.ts +++ b/test/DODOEthProxyAsBase.test.ts @@ -44,6 +44,9 @@ async function init(ctx: DODOContext): Promise { .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; @@ -102,12 +105,11 @@ describe("DODO ETH PROXY", () => { it("buy", async () => { const buyAmount = "1"; await logGas( - DODOEthProxy.methods - .buyEthWithToken( - ctx.QUOTE.options.address, - decimalStr(buyAmount), - decimalStr("200") - ), + DODOEthProxy.methods.buyEthWithToken( + ctx.QUOTE.options.address, + decimalStr(buyAmount), + decimalStr("200") + ), ctx.sendParam(trader), "buy ETH with token directly" ); @@ -123,12 +125,11 @@ describe("DODO ETH PROXY", () => { it("sell", async () => { const sellAmount = "1"; await logGas( - DODOEthProxy.methods - .sellEthToToken( - ctx.QUOTE.options.address, - decimalStr(sellAmount), - decimalStr("50") - ), + DODOEthProxy.methods.sellEthToToken( + ctx.QUOTE.options.address, + decimalStr(sellAmount), + decimalStr("50") + ), ctx.sendParam(trader, sellAmount), "sell ETH to token directly" ); diff --git a/test/DODOEthProxyAsQuote.test.ts b/test/DODOEthProxyAsQuote.test.ts index 04b1932..1941803 100644 --- a/test/DODOEthProxyAsQuote.test.ts +++ b/test/DODOEthProxyAsQuote.test.ts @@ -44,6 +44,9 @@ async function init(ctx: DODOContext): Promise { .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; @@ -103,12 +106,15 @@ describe("DODO ETH PROXY", () => { const maxPayEthAmount = "2.1"; const ethInPoolBefore = decimalStr("10"); const traderEthBalanceBefore = await ctx.Web3.eth.getBalance(trader); - const txReceipt: TransactionReceipt = await logGas(DODOEthProxy.methods - .buyTokenWithEth( + 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"); + ), + ctx.sendParam(trader, maxPayEthAmount), + "buy token with ETH directly" + ); const ethInPoolAfter = "12056338203652739553"; assert.strictEqual( await ctx.DODO.methods._QUOTE_BALANCE_().call(), @@ -133,12 +139,11 @@ describe("DODO ETH PROXY", () => { it("sell", async () => { const minReceiveEthAmount = "0.45"; await logGas( - DODOEthProxy.methods - .sellTokenToEth( - ctx.BASE.options.address, - decimalStr("50"), - decimalStr(minReceiveEthAmount) - ), + DODOEthProxy.methods.sellTokenToEth( + ctx.BASE.options.address, + decimalStr("50"), + decimalStr(minReceiveEthAmount) + ), ctx.sendParam(trader), "sell token to ETH directly" ); 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 + ); + }); + }); +}); diff --git a/test/utils/Context.ts b/test/utils/Context.ts index 451bd44..2bf61ae 100644 --- a/test/utils/Context.ts +++ b/test/utils/Context.ts @@ -5,13 +5,14 @@ */ -import { EVM, getDefaultWeb3 } from "./EVM"; -import Web3 from "web3"; -import { Contract } from "web3-eth-contract"; -import BigNumber from "bignumber.js"; -import * as contracts from "./Contracts"; -import { decimalStr, gweiStr, MAX_UINT256 } from "./Converter"; -import * as log from "./Log"; +import BigNumber from 'bignumber.js'; +import Web3 from 'web3'; +import { Contract } from 'web3-eth-contract'; + +import * as contracts from './Contracts'; +import { decimalStr, gweiStr, MAX_UINT256 } from './Converter'; +import { EVM, getDefaultWeb3 } from './EVM'; +import * as log from './Log'; BigNumber.config({ EXPONENTIAL_AT: 1000, @@ -19,10 +20,10 @@ BigNumber.config({ }); export interface DODOContextInitConfig { - lpFeeRate: string, - mtFeeRate: string, - k: string, - gasPriceLimit: string, + lpFeeRate: string; + mtFeeRate: string; + k: string; + gasPriceLimit: string; } /* @@ -43,60 +44,99 @@ export let DefaultDODOContextInitConfig = { mtFeeRate: decimalStr("0.001"), k: decimalStr("0.1"), gasPriceLimit: gweiStr("100"), -} +}; export class DODOContext { - EVM: EVM - Web3: Web3 - DODO: Contract - DODOZoo: Contract - BASE: Contract - BaseCapital: Contract - QUOTE: Contract - QuoteCapital: Contract - ORACLE: Contract - Deployer: string - Supervisor: string - Maintainer: string - spareAccounts: string[] + EVM: EVM; + Web3: Web3; + DODO: Contract; + DODOZoo: Contract; + BASE: Contract; + BaseCapital: Contract; + QUOTE: Contract; + QuoteCapital: Contract; + ORACLE: Contract; + Deployer: string; + Supervisor: string; + Maintainer: string; + spareAccounts: string[]; - constructor() { } + constructor() {} async init(config: DODOContextInitConfig) { - this.EVM = new EVM - this.Web3 = getDefaultWeb3() - var cloneFactory = await contracts.newContract(contracts.CLONE_FACTORY_CONTRACT_NAME) + this.EVM = new EVM(); + this.Web3 = getDefaultWeb3(); + var cloneFactory = await contracts.newContract( + contracts.CLONE_FACTORY_CONTRACT_NAME + ); - this.BASE = await contracts.newContract(contracts.TEST_ERC20_CONTRACT_NAME, ["TestBase", 18]) - this.QUOTE = await contracts.newContract(contracts.TEST_ERC20_CONTRACT_NAME, ["TestQuote", 18]) - this.ORACLE = await contracts.newContract(contracts.NAIVE_ORACLE_CONTRACT_NAME) + this.BASE = await contracts.newContract( + contracts.TEST_ERC20_CONTRACT_NAME, + ["TestBase", 18] + ); + this.QUOTE = await contracts.newContract( + contracts.TEST_ERC20_CONTRACT_NAME, + ["TestQuote", 18] + ); + this.ORACLE = await contracts.newContract( + contracts.NAIVE_ORACLE_CONTRACT_NAME + ); const allAccounts = await this.Web3.eth.getAccounts(); - this.Deployer = allAccounts[0] - this.Supervisor = allAccounts[1] - this.Maintainer = allAccounts[2] - this.spareAccounts = allAccounts.slice(3, 10) + this.Deployer = allAccounts[0]; + this.Supervisor = allAccounts[1]; + this.Maintainer = allAccounts[2]; + this.spareAccounts = allAccounts.slice(3, 10); - var DODOTemplate = await contracts.newContract(contracts.DODO_CONTRACT_NAME) - this.DODOZoo = await contracts.newContract(contracts.DODO_ZOO_CONTRACT_NAME, [DODOTemplate.options.address, cloneFactory.options.address, this.Supervisor]) + var DODOTemplate = await contracts.newContract( + contracts.DODO_CONTRACT_NAME + ); + this.DODOZoo = await contracts.newContract( + contracts.DODO_ZOO_CONTRACT_NAME, + [ + DODOTemplate.options.address, + cloneFactory.options.address, + this.Supervisor, + ] + ); - await this.DODOZoo.methods.breedDODO( - this.Maintainer, - this.BASE.options.address, - this.QUOTE.options.address, - this.ORACLE.options.address, - config.lpFeeRate, - config.mtFeeRate, - config.k, - config.gasPriceLimit - ).send(this.sendParam(this.Deployer)) + await this.DODOZoo.methods + .breedDODO( + this.Maintainer, + this.BASE.options.address, + this.QUOTE.options.address, + this.ORACLE.options.address, + config.lpFeeRate, + config.mtFeeRate, + config.k, + config.gasPriceLimit + ) + .send(this.sendParam(this.Deployer)); - this.DODO = contracts.getContractWithAddress(contracts.DODO_CONTRACT_NAME, await this.DODOZoo.methods.getDODO(this.BASE.options.address, this.QUOTE.options.address).call()) + this.DODO = contracts.getContractWithAddress( + contracts.DODO_CONTRACT_NAME, + await this.DODOZoo.methods + .getDODO(this.BASE.options.address, this.QUOTE.options.address) + .call() + ); + await this.DODO.methods + .enableBaseDeposit() + .send(this.sendParam(this.Deployer)); + await this.DODO.methods + .enableQuoteDeposit() + .send(this.sendParam(this.Deployer)); + await this.DODO.methods.enableTrading().send(this.sendParam(this.Deployer)); - this.BaseCapital = contracts.getContractWithAddress(contracts.DODO_LP_TOKEN_CONTRACT_NAME, await this.DODO.methods._BASE_CAPITAL_TOKEN_().call()) - this.QuoteCapital = contracts.getContractWithAddress(contracts.DODO_LP_TOKEN_CONTRACT_NAME, await this.DODO.methods._QUOTE_CAPITAL_TOKEN_().call()) + this.BaseCapital = contracts.getContractWithAddress( + contracts.DODO_LP_TOKEN_CONTRACT_NAME, + await this.DODO.methods._BASE_CAPITAL_TOKEN_().call() + ); + this.QuoteCapital = contracts.getContractWithAddress( + contracts.DODO_LP_TOKEN_CONTRACT_NAME, + await this.DODO.methods._QUOTE_CAPITAL_TOKEN_().call() + ); - console.log(log.blueText("[Init dodo context]")) + console.log(log.blueText("[Init dodo context]")); } sendParam(sender, value = "0") { @@ -104,27 +144,37 @@ export class DODOContext { from: sender, gas: process.env["COVERAGE"] ? 10000000000 : 7000000, gasPrice: process.env.GAS_PRICE, - value: decimalStr(value) - } + value: decimalStr(value), + }; } async setOraclePrice(price: string) { - await this.ORACLE.methods.setPrice(price).send(this.sendParam(this.Deployer)) + await this.ORACLE.methods + .setPrice(price) + .send(this.sendParam(this.Deployer)); } async mintTestToken(to: string, base: string, quote: string) { - await this.BASE.methods.mint(to, base).send(this.sendParam(this.Deployer)) - await this.QUOTE.methods.mint(to, quote).send(this.sendParam(this.Deployer)) + await this.BASE.methods.mint(to, base).send(this.sendParam(this.Deployer)); + await this.QUOTE.methods + .mint(to, quote) + .send(this.sendParam(this.Deployer)); } async approveDODO(account: string) { - await this.BASE.methods.approve(this.DODO.options.address, MAX_UINT256).send(this.sendParam(account)) - await this.QUOTE.methods.approve(this.DODO.options.address, MAX_UINT256).send(this.sendParam(account)) + await this.BASE.methods + .approve(this.DODO.options.address, MAX_UINT256) + .send(this.sendParam(account)); + await this.QUOTE.methods + .approve(this.DODO.options.address, MAX_UINT256) + .send(this.sendParam(account)); } } -export async function getDODOContext(config: DODOContextInitConfig = DefaultDODOContextInitConfig): Promise { - var context = new DODOContext() - await context.init(config) - return context -} \ No newline at end of file +export async function getDODOContext( + config: DODOContextInitConfig = DefaultDODOContextInitConfig +): Promise { + var context = new DODOContext(); + await context.init(config); + return context; +}