From af48643f929e701f8f2ff2e0c4b82e6014bb292b Mon Sep 17 00:00:00 2001 From: mingda Date: Thu, 26 Nov 2020 20:13:16 +0800 Subject: [PATCH] finish DPP test --- contracts/DODOPrivatePool/impl/DPPVault.sol | 46 +++--- test/DPP/owner.test.ts | 63 ++++++++ test/DPP/reset.test.ts | 155 ++++++++++++++++++++ 3 files changed, 243 insertions(+), 21 deletions(-) create mode 100644 test/DPP/owner.test.ts create mode 100644 test/DPP/reset.test.ts diff --git a/contracts/DODOPrivatePool/impl/DPPVault.sol b/contracts/DODOPrivatePool/impl/DPPVault.sol index 86676b3..471109f 100644 --- a/contracts/DODOPrivatePool/impl/DPPVault.sol +++ b/contracts/DODOPrivatePool/impl/DPPVault.sol @@ -15,7 +15,7 @@ import {SafeMath} from "../../lib/SafeMath.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol"; import {SafeERC20} from "../../lib/SafeERC20.sol"; import {Ownable} from "../../lib/Ownable.sol"; -import {ISmartApprove} from "../../intf/ISmartApprove.sol"; +import {PMMPricing} from "../../lib/PMMPricing.sol"; contract DPPVault is DPPStorage { using SafeMath for uint256; @@ -45,15 +45,16 @@ contract DPPVault is DPPStorage { // ============ Set Status ============ - function setTarget(uint256 baseTarget, uint256 quoteTarget) public onlyOwner { + function setTarget(uint256 baseTarget, uint256 quoteTarget) public preventReentrant onlyOwner { _BASE_TARGET_ = baseTarget; _QUOTE_TARGET_ = quoteTarget; - _checkStatus(); + _setRState(); } function _syncReserve() internal { _BASE_RESERVE_ = _BASE_TOKEN_.balanceOf(address(this)); _QUOTE_RESERVE_ = _QUOTE_TOKEN_.balanceOf(address(this)); + _setRState(); } function _resetTargetAndReserve() internal { @@ -61,6 +62,7 @@ contract DPPVault is DPPStorage { _QUOTE_TARGET_ = _QUOTE_TOKEN_.balanceOf(address(this)); _BASE_RESERVE_ = _BASE_TARGET_; _QUOTE_RESERVE_ = _QUOTE_TARGET_; + _setRState(); } function reset( @@ -71,22 +73,28 @@ contract DPPVault is DPPStorage { uint256 newK, uint256 baseOutAmount, uint256 quoteOutAmount - ) public onlyOwner { - require(newK > 0 && newK <= 10**18, "K OUT OF RANGE!"); - _transferBaseOut(assetTo, baseOutAmount); - _transferQuoteOut(assetTo, quoteOutAmount); - _resetTargetAndReserve(); + ) public preventReentrant onlyOwner { + require(newK >= 1e12 && newK <= 1e18, "K_OUT_OF_RANGE"); + require(newI > 0 && newI <= 1e36, "I_OUT_OF_RANGE"); _LP_FEE_RATE_MODEL_.setFeeRate(newLpFeeRate); _MT_FEE_RATE_MODEL_.setFeeRate(newMtFeeRate); _I_.set(newI); _K_.set(newK); + _transferBaseOut(assetTo, baseOutAmount); + _transferQuoteOut(assetTo, quoteOutAmount); + _resetTargetAndReserve(); } - function _checkStatus() internal view { - require( - !(_BASE_RESERVE_ < _BASE_TARGET_ && _QUOTE_RESERVE_ < _QUOTE_TARGET_), - "STATUS_WRONG" - ); + function _setRState() internal { + if (_BASE_RESERVE_ == _BASE_TARGET_ && _QUOTE_RESERVE_ == _QUOTE_TARGET_) { + _RState_ = PMMPricing.RState.ONE; + } else if (_BASE_RESERVE_ > _BASE_TARGET_) { + _RState_ = PMMPricing.RState.BELOW_ONE; + } else if (_QUOTE_RESERVE_ > _QUOTE_TARGET_) { + _RState_ = PMMPricing.RState.ABOVE_ONE; + } else { + require(false, "R_STATE_WRONG"); + } } // ============ Assets Transfer ============ @@ -104,15 +112,11 @@ contract DPPVault is DPPStorage { } function retrieve( - address payable to, + address to, address token, uint256 amount - ) external onlyOwner { - require(to != address(_BASE_TOKEN_) && to != address(_QUOTE_TOKEN_), "USE_WITHDRAW"); - if (token == 0x000000000000000000000000000000000000000E) { - to.transfer(amount); - } else { - IERC20(token).safeTransfer(msg.sender, amount); - } + ) external preventReentrant onlyOwner { + require(token != address(_BASE_TOKEN_) && token != address(_QUOTE_TOKEN_), "USE_RESET"); + IERC20(token).safeTransfer(to, amount); } } diff --git a/test/DPP/owner.test.ts b/test/DPP/owner.test.ts new file mode 100644 index 0000000..6bcfceb --- /dev/null +++ b/test/DPP/owner.test.ts @@ -0,0 +1,63 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +// import * as assert from 'assert'; + +import { DPPContext, getDPPContext } from '../utils/DPPContext'; +import { assert } from 'chai'; +const truffleAssert = require('truffle-assertions'); + +async function init(ctx: DPPContext): Promise { } + +describe("Admin Set", () => { + let snapshotId: string; + let ctx: DPPContext; + + before(async () => { + ctx = await getDPPContext(); + await init(ctx); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("setting", () => { + + it("set addresses", async () => { + + var tempAddress = ctx.SpareAccounts[0] + + await ctx.DPP.methods.setLpFeeRateModel(tempAddress).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.setMtFeeRateModel(tempAddress).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.setTradePermissionManager(tempAddress).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.setMaintainer(tempAddress).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.setGasPriceSource(tempAddress).send(ctx.sendParam(ctx.Deployer)) + + assert.equal(await ctx.DPP.methods._LP_FEE_RATE_MODEL_().call(), tempAddress) + assert.equal(await ctx.DPP.methods._MT_FEE_RATE_MODEL_().call(), tempAddress) + assert.equal(await ctx.DPP.methods._TRADE_PERMISSION_().call(), tempAddress) + assert.equal(await ctx.DPP.methods._MAINTAINER_().call(), tempAddress) + assert.equal(await ctx.DPP.methods._GAS_PRICE_LIMIT_().call(), tempAddress) + + }); + + it("set buy sell", async () => { + await ctx.DPP.methods.setBuy(false).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.setSell(false).send(ctx.sendParam(ctx.Deployer)) + + await truffleAssert.reverts(ctx.DPP.methods.sellQuote(ctx.Deployer).send(ctx.sendParam(ctx.Deployer)), "TRADER_BUY_NOT_ALLOWED") + + await truffleAssert.reverts(ctx.DPP.methods.sellBase(ctx.Deployer).send(ctx.sendParam(ctx.Deployer)), "TRADER_SELL_NOT_ALLOWED") + }) + + }); +}); \ No newline at end of file diff --git a/test/DPP/reset.test.ts b/test/DPP/reset.test.ts new file mode 100644 index 0000000..577927f --- /dev/null +++ b/test/DPP/reset.test.ts @@ -0,0 +1,155 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +// import * as assert from 'assert'; + +import { decimalStr } from '../utils/Converter'; +import { DPPContext, getDPPContext } from '../utils/DPPContext'; +import { assert } from 'chai'; +import { EXTERNAL_VALUE_NAME, getContractWithAddress, MINTABLE_ERC20_CONTRACT_NAME, newContract } from '../utils/Contracts'; +import { sendParam } from '../../script/utils'; +const truffleAssert = require('truffle-assertions'); + +let lp: string; + +async function init(ctx: DPPContext): Promise { + lp = ctx.Deployer + + await ctx.mintTestToken(lp, decimalStr("100"), decimalStr("10000")); + + var baseAmount = decimalStr("10") + var quoteAmount = decimalStr("1000") + var lpFeeRate = decimalStr("0.002") + var mtFeeRate = decimalStr("0.001") + var iValue = decimalStr("200") + var kValue = decimalStr("0.2") + await ctx.transferBaseToDPP(lp, baseAmount) + await ctx.transferQuoteToDPP(lp, quoteAmount) + await ctx.DPP.methods.reset(lp, lpFeeRate, mtFeeRate, iValue, kValue, "0", "0").send(ctx.sendParam(ctx.Deployer)) +} + +describe("DPP Trader", () => { + let snapshotId: string; + let ctx: DPPContext; + + before(async () => { + ctx = await getDPPContext(); + await init(ctx); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("reset", () => { + + it("reset with asset input", async () => { + + var lpFeeRate = decimalStr("0.01") + var mtFeeRate = decimalStr("0.02") + var iValue = decimalStr("300") + var kValue = decimalStr("0.3") + await ctx.transferBaseToDPP(lp, decimalStr("10")) + await ctx.transferQuoteToDPP(lp, decimalStr("1000")) + await ctx.DPP.methods.reset(lp, lpFeeRate, mtFeeRate, iValue, kValue, "0", "0").send(ctx.sendParam(ctx.Deployer)) + + var state = await ctx.DPP.methods.getPMMState().call() + assert.equal(state.B, decimalStr("20")) + assert.equal(state.Q, decimalStr("2000")) + assert.equal(state.B0, decimalStr("20")) + assert.equal(state.Q0, decimalStr("2000")) + assert.equal(state.i, iValue) + assert.equal(state.K, kValue) + assert.equal(await ctx.DPP.methods.getLpFeeRate(lp).call(), lpFeeRate) + assert.equal(await ctx.DPP.methods.getMtFeeRate(lp).call(), mtFeeRate) + }); + + it("reset with asset output", async () => { + var lpFeeRate = decimalStr("0.01") + var mtFeeRate = decimalStr("0.02") + var iValue = decimalStr("300") + var kValue = decimalStr("0.3") + await ctx.DPP.methods.reset(lp, lpFeeRate, mtFeeRate, iValue, kValue, decimalStr("1"), decimalStr("100")).send(ctx.sendParam(ctx.Deployer)) + + var state = await ctx.DPP.methods.getPMMState().call() + assert.equal(state.B, decimalStr("9")) + assert.equal(state.Q, decimalStr("900")) + assert.equal(state.B0, decimalStr("9")) + assert.equal(state.Q0, decimalStr("900")) + assert.equal(state.i, iValue) + assert.equal(state.K, kValue) + assert.equal(await ctx.DPP.methods.getLpFeeRate(lp).call(), lpFeeRate) + assert.equal(await ctx.DPP.methods.getMtFeeRate(lp).call(), mtFeeRate) + }) + + it("reset without asset input/output", async () => { + var lpFeeRate = decimalStr("0.01") + var mtFeeRate = decimalStr("0.02") + var iValue = decimalStr("300") + var kValue = decimalStr("0.3") + await ctx.DPP.methods.reset(lp, lpFeeRate, mtFeeRate, iValue, kValue, "0", "0").send(ctx.sendParam(ctx.Deployer)) + + var state = await ctx.DPP.methods.getPMMState().call() + assert.equal(state.B, decimalStr("10")) + assert.equal(state.Q, decimalStr("1000")) + assert.equal(state.B0, decimalStr("10")) + assert.equal(state.Q0, decimalStr("1000")) + assert.equal(state.i, iValue) + assert.equal(state.K, kValue) + assert.equal(await ctx.DPP.methods.getLpFeeRate(lp).call(), lpFeeRate) + assert.equal(await ctx.DPP.methods.getMtFeeRate(lp).call(), mtFeeRate) + }) + + }); + + describe("retrieve", async () => { + + it("retrieve another token", async () => { + var otherToken = await newContract( + MINTABLE_ERC20_CONTRACT_NAME, + ["Test", "TEST", 18] + ); + await otherToken.methods.mint(ctx.DPP.options.address, decimalStr("10")).send(ctx.sendParam(ctx.Deployer)) + await ctx.DPP.methods.retrieve(ctx.Deployer, otherToken.options.address, decimalStr("10")).send(ctx.sendParam(ctx.Deployer)) + assert.equal(await otherToken.methods.balanceOf(ctx.DPP.options.address).call(), "0") + assert.equal(await otherToken.methods.balanceOf(ctx.Deployer).call(), decimalStr("10")) + }) + + }) + + describe("revert", async () => { + it("can not retrieve base or quote", async () => { + await truffleAssert.reverts( + ctx.DPP.methods.retrieve(ctx.Deployer, ctx.BASE.options.address, decimalStr("1")).send(ctx.sendParam(ctx.Deployer)), "USE_RESET" + ) + + await truffleAssert.reverts( + ctx.DPP.methods.retrieve(ctx.Deployer, ctx.QUOTE.options.address, decimalStr("1")).send(ctx.sendParam(ctx.Deployer)), "USE_RESET" + ) + }) + + it("i or k can not out of range", async () => { + await truffleAssert.reverts( + ctx.DPP.methods.reset(lp, "0", "0", "0", decimalStr("1"), "0", "0").send(ctx.sendParam(ctx.Deployer)), "I_OUT_OF_RANGE" + ) + await truffleAssert.reverts( + ctx.DPP.methods.reset(lp, "0", "0", "10000000000000000000000000000000000000", decimalStr("1"), "0", "0").send(ctx.sendParam(ctx.Deployer)), "I_OUT_OF_RANGE" + ) + await truffleAssert.reverts( + ctx.DPP.methods.reset(lp, "0", "0", decimalStr("1"), "1", "0", "0").send(ctx.sendParam(ctx.Deployer)), "K_OUT_OF_RANGE" + ) + await truffleAssert.reverts( + ctx.DPP.methods.reset(lp, "0", "0", decimalStr("1"), decimalStr("2"), "0", "0").send(ctx.sendParam(ctx.Deployer)), "K_OUT_OF_RANGE" + ) + }) + }) + +}); \ No newline at end of file