From ad7ed919d0e187eef89cf1c2cad8fe1a3a50bda1 Mon Sep 17 00:00:00 2001 From: mingda Date: Fri, 6 Nov 2020 16:03:18 +0800 Subject: [PATCH] set external call interface --- .../DODOVendorMachine/impl/DVMFunding.sol | 22 ++++--- .../DODOVendorMachine/impl/DVMTrader.sol | 63 +++++++++++-------- .../DODOVendorMachine/intf/IExternalCall.sol | 13 ---- contracts/intf/IDODOCallee.sol | 26 ++++++++ contracts/lib/DODOMath.sol | 1 + contracts/lib/PermissionManager.sol | 16 ++--- test/DVM/trader.test.ts | 3 + 7 files changed, 90 insertions(+), 54 deletions(-) delete mode 100644 contracts/DODOVendorMachine/intf/IExternalCall.sol create mode 100644 contracts/intf/IDODOCallee.sol diff --git a/contracts/DODOVendorMachine/impl/DVMFunding.sol b/contracts/DODOVendorMachine/impl/DVMFunding.sol index 346cc72..9e715c2 100644 --- a/contracts/DODOVendorMachine/impl/DVMFunding.sol +++ b/contracts/DODOVendorMachine/impl/DVMFunding.sol @@ -10,9 +10,10 @@ pragma experimental ABIEncoderV2; import {DVMStorage} from "./DVMStorage.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol"; +import {IDODOCallee} from "../../intf/IDODOCallee.sol"; contract DVMFunding is DVMStorage { - function buyShares(address to) external returns (uint256) { + function buyShares(address to) external preventReentrant returns (uint256) { uint256 baseInput = _VAULT_.getBaseInput(); uint256 quoteInput = _VAULT_.getQuoteInput(); require(baseInput > 0, "NO_BASE_INPUT"); @@ -46,17 +47,24 @@ contract DVMFunding is DVMStorage { _VAULT_.sync(); } - function sellShares(address to, uint256 amount) external returns (uint256) { - require(_VAULT_.balanceOf(msg.sender) >= amount, "SHARES_NOT_ENOUGH"); + function sellShares( + address to, + uint256 shareAmount, + bytes calldata data + ) external preventReentrant returns (uint256) { + require(_VAULT_.balanceOf(msg.sender) >= shareAmount, "SHARES_NOT_ENOUGH"); (uint256 baseBalance, uint256 quoteBalance) = _VAULT_.getVaultBalance(); uint256 totalShares = _VAULT_.totalSupply(); - _VAULT_.burn(msg.sender, amount); - _VAULT_.transferBaseOut(to, baseBalance.mul(amount).div(totalShares)); - _VAULT_.transferQuoteOut(to, quoteBalance.mul(amount).div(totalShares)); + _VAULT_.burn(msg.sender, shareAmount); + uint256 baseAmount = baseBalance.mul(shareAmount).div(totalShares); + uint256 quoteAmount = quoteBalance.mul(shareAmount).div(totalShares); + _VAULT_.transferBaseOut(to, baseAmount); + _VAULT_.transferQuoteOut(to, quoteAmount); _VAULT_.sync(); + if (data.length > 0) IDODOCallee(to, shareAmount, baseAmount, quoteAmount, data); } - function retrieve(address to) external { + function retrieve(address to) external preventReentrant { (uint256 baseBalance, uint256 quoteBalance) = _VAULT_.getVaultBalance(); (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); if (baseBalance.sub(baseReserve) > 0) { diff --git a/contracts/DODOVendorMachine/impl/DVMTrader.sol b/contracts/DODOVendorMachine/impl/DVMTrader.sol index 7cc064e..657581f 100644 --- a/contracts/DODOVendorMachine/impl/DVMTrader.sol +++ b/contracts/DODOVendorMachine/impl/DVMTrader.sol @@ -12,12 +12,17 @@ import {DVMStorage} from "./DVMStorage.sol"; import {SafeMath} from "../../lib/SafeMath.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol"; import {DODOMath} from "../../lib/DODOMath.sol"; -import {IExternalCall} from "../intf/IExternalCall.sol"; +import {IDODOCallee} from "../../intf/IDODOCallee.sol"; contract DVMTrader is DVMStorage { using SafeMath for uint256; - function sellBase(address to) external isSellAllow(to) returns (uint256 receiveQuoteAmount) { + function sellBase(address to) + external + preventReentrant + isSellAllow(to) + returns (uint256 receiveQuoteAmount) + { uint256 baseInput = _VAULT_.getBaseInput(); uint256 mtFee; (receiveQuoteAmount, mtFee) = querySellBase(to, baseInput); @@ -29,7 +34,12 @@ contract DVMTrader is DVMStorage { return receiveQuoteAmount; } - function sellQuote(address to) external isBuyAllow(to) returns (uint256 receiveBaseAmount) { + function sellQuote(address to) + external + preventReentrant + isBuyAllow(to) + returns (uint256 receiveBaseAmount) + { uint256 quoteInput = _VAULT_.getQuoteInput(); uint256 mtFee; (receiveBaseAmount, mtFee) = querySellQuote(to, quoteInput); @@ -45,12 +55,13 @@ contract DVMTrader is DVMStorage { uint256 baseAmount, uint256 quoteAmount, address assetTo, - address call, bytes calldata data - ) external { + ) external preventReentrant { _VAULT_.transferBaseOut(assetTo, baseAmount); _VAULT_.transferQuoteOut(assetTo, quoteAmount); - IExternalCall(call).DVMCall(data); + + if (data.length > 0) + IDODOCallee(assetTo).DVMFlashLoanCall(msg.sender, baseAmount, quoteAmount, data); (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); (uint256 baseBalance, uint256 quoteBalance) = _VAULT_.getVaultBalance(); @@ -102,26 +113,6 @@ contract DVMTrader is DVMStorage { return (receiveQuoteAmount, mtFee); } - // 这是一个仅供查询的合约,所有交易都是基于先给input,再输出output的 - // 所以想要买10ETH,这个函数可以给你一个大概的成本,你用这个成本输入,最后能否得到10ETH是要看情况的 - function queryBuyBase(address trader, uint256 receiveBaseAmount) - public - view - returns (uint256 payQuoteAmount) - { - uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); - uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader); - uint256 validReceiveBaseAmount = DecimalMath.divCeil( - receiveBaseAmount, - DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate) - ); - (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); - uint256 B0 = calculateBase0(baseReserve, quoteReserve); - uint256 B2 = baseReserve.sub(validReceiveBaseAmount); - payQuoteAmount = DODOMath._GeneralIntegrate(B0, baseReserve, B2, _I_, _K_); - return payQuoteAmount; - } - function querySellQuote(address trader, uint256 payQuoteAmount) public view @@ -145,6 +136,26 @@ contract DVMTrader is DVMStorage { return (receiveBaseAmount, mtFee); } + // 这是一个仅供查询的合约,所有交易都是基于先给input,再输出output的 + // 所以想要买10ETH,这个函数可以给你一个大概的成本,你用这个成本输入,最后能否得到10ETH是要看情况的 + function queryBuyBase(address trader, uint256 receiveBaseAmount) + public + view + returns (uint256 payQuoteAmount) + { + uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); + uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader); + uint256 validReceiveBaseAmount = DecimalMath.divCeil( + receiveBaseAmount, + DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate) + ); + (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); + uint256 B0 = calculateBase0(baseReserve, quoteReserve); + uint256 B2 = baseReserve.sub(validReceiveBaseAmount); + payQuoteAmount = DODOMath._GeneralIntegrate(B0, baseReserve, B2, _I_, _K_); + return payQuoteAmount; + } + function queryBuyQuote(address trader, uint256 receiveQuoteAmount) public view diff --git a/contracts/DODOVendorMachine/intf/IExternalCall.sol b/contracts/DODOVendorMachine/intf/IExternalCall.sol deleted file mode 100644 index fbd517e..0000000 --- a/contracts/DODOVendorMachine/intf/IExternalCall.sol +++ /dev/null @@ -1,13 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -pragma solidity 0.6.9; -pragma experimental ABIEncoderV2; - -interface IExternalCall { - function DVMCall(bytes calldata data) external; -} diff --git a/contracts/intf/IDODOCallee.sol b/contracts/intf/IDODOCallee.sol new file mode 100644 index 0000000..5bde65f --- /dev/null +++ b/contracts/intf/IDODOCallee.sol @@ -0,0 +1,26 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +interface IDODOCallee { + function DVMSellShareCall( + address sender, + uint256 burnShareAmount, + uint256 baseAmount, + uint256 quoteAmount, + bytes calldata data + ) external; + + function DVMFlashLoanCall( + address sender, + uint256 baseAmount, + uint256 quoteAmount, + bytes calldata data + ) external; +} diff --git a/contracts/lib/DODOMath.sol b/contracts/lib/DODOMath.sol index 783b806..6a726ae 100644 --- a/contracts/lib/DODOMath.sol +++ b/contracts/lib/DODOMath.sol @@ -53,6 +53,7 @@ library DODOMath { note: another root is negative, abondan if deltaBSig=true, then Q2>Q1 if deltaBSig=false, then Q2 bool) internal _whitelist_; mapping(address => bool) internal _blacklist_; function isAllowed(address account) external view returns (bool) { - if (_BLACKLIST_MODE_ON_) { - return !_blacklist_[account]; - } else { + if (_WHITELIST_MODE_ON_) { return _whitelist_[account]; + } else { + return !_blacklist_[account]; } } - function openBlacklist() external onlyOwner { - _BLACKLIST_MODE_ON_ = true; + function openBlacklistMode() external onlyOwner { + _WHITELIST_MODE_ON_ = false; } - function openWhitelist() external onlyOwner { - _BLACKLIST_MODE_ON_ = true; + function openWhitelistMode() external onlyOwner { + _WHITELIST_MODE_ON_ = true; } function addToWhitelist(address account) external onlyOwner { diff --git a/test/DVM/trader.test.ts b/test/DVM/trader.test.ts index e63d7e9..1b1b5f3 100644 --- a/test/DVM/trader.test.ts +++ b/test/DVM/trader.test.ts @@ -51,6 +51,9 @@ describe("Trader", () => { }); describe("trade", () => { + // it.only("gas cost", async () => { + // await logGas(ctx.DVM.methods.calculateBase0(decimalStr("200"), decimalStr("1")), ctx.sendParam(trader), "calculate base0") + // }) it("buy & sell", async () => { console.log("BASE0 before buy", await ctx.DVM.methods.getBase0().call())