From 81dc1c15a0e30a718dcffbb2a5086cfbf47d8fb7 Mon Sep 17 00:00:00 2001 From: mingda Date: Fri, 6 Nov 2020 00:31:30 +0800 Subject: [PATCH] flash loan --- contracts/DODOVendorMachine/impl/DVM.sol | 2 - .../DODOVendorMachine/impl/DVMStorage.sol | 34 +++++++++---- .../DODOVendorMachine/impl/DVMTrader.sol | 50 ++++++++++++------- contracts/DODOVendorMachine/impl/DVMVault.sol | 8 ++- contracts/DODOVendorMachine/intf/IDVM.sol | 1 - contracts/Factory/DVMFactory.sol | 1 - contracts/intf/IFeeRateModel.sol | 2 +- contracts/lib/ConstFeeRateModel.sol | 6 +-- 8 files changed, 65 insertions(+), 39 deletions(-) diff --git a/contracts/DODOVendorMachine/impl/DVM.sol b/contracts/DODOVendorMachine/impl/DVM.sol index 8310d88..70ea6d2 100644 --- a/contracts/DODOVendorMachine/impl/DVM.sol +++ b/contracts/DODOVendorMachine/impl/DVM.sol @@ -22,7 +22,6 @@ contract DVM is DVMTrader, DVMFunding { address lpFeeRateModel, address mtFeeRateModel, address tradePermissionManager, - address fundingPermissionManager, uint256 i, uint256 k ) external { @@ -33,7 +32,6 @@ contract DVM is DVMTrader, DVMFunding { _LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel); _MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel); _TRADE_PERMISSION_ = IPermissionManager(tradePermissionManager); - _FUNDING_PERMISSION_ = IPermissionManager(fundingPermissionManager); _MAINTAINER_ = maintainer; _I_ = i; _K_ = k; diff --git a/contracts/DODOVendorMachine/impl/DVMStorage.sol b/contracts/DODOVendorMachine/impl/DVMStorage.sol index 848fc2f..e2712f3 100644 --- a/contracts/DODOVendorMachine/impl/DVMStorage.sol +++ b/contracts/DODOVendorMachine/impl/DVMStorage.sol @@ -22,16 +22,14 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard { // ============ Variables for Control ============ - bool public _CLOSED_; uint256 public _GAS_PRICE_LIMIT_; // ============ Advanced Controls ============ - bool public _BUYING_ALLOWED_; - bool public _SELLING_ALLOWED_; + bool public _BUYING_CLOSE_; + bool public _SELLING_CLOSE_; IPermissionManager public _TRADE_PERMISSION_; - IPermissionManager public _FUNDING_PERMISSION_; // ============ Core Address ============ @@ -51,8 +49,16 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard { // ============ Modifiers ============ - modifier notClosed() { - require(!_CLOSED_, "DODO_CLOSED"); + modifier isBuyAllow(address trader) { + require(!_BUYING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(trader), "TRADER_BUY_NOT_ALLOWED"); + _; + } + + modifier isSellAllow(address trader) { + require( + !_SELLING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(trader), + "TRADER_SELL_NOT_ALLOWED" + ); _; } @@ -83,11 +89,19 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard { _TRADE_PERMISSION_ = IPermissionManager(newTradePermissionManager); } - function setFundingPermissionManager(address newFundingPermissionManager) external onlyOwner { - _FUNDING_PERMISSION_ = IPermissionManager(newFundingPermissionManager); - } - function setMaintainer(address newMaintainer) external onlyOwner { _MAINTAINER_ = newMaintainer; } + + function setGasPriceLimit(uint256 newGasPriceLimit) external onlyOwner { + _GAS_PRICE_LIMIT_ = newGasPriceLimit; + } + + function setBuy(bool open) external onlyOwner { + _BUYING_CLOSE_ = !open; + } + + function setSell(bool open) external onlyOwner { + _SELLING_CLOSE_ = !open; + } } diff --git a/contracts/DODOVendorMachine/impl/DVMTrader.sol b/contracts/DODOVendorMachine/impl/DVMTrader.sol index 52d0286..086d5eb 100644 --- a/contracts/DODOVendorMachine/impl/DVMTrader.sol +++ b/contracts/DODOVendorMachine/impl/DVMTrader.sol @@ -17,7 +17,7 @@ import {IExternalCall} from "../intf/IExternalCall.sol"; contract DVMTrader is DVMStorage { using SafeMath for uint256; - function sellBase(address to) external returns (uint256 receiveQuoteAmount) { + function sellBase(address to) external isSellAllow(to) returns (uint256 receiveQuoteAmount) { uint256 baseInput = _VAULT_.getBaseInput(); uint256 mtFee; (receiveQuoteAmount, mtFee) = querySellBase(to, baseInput); @@ -29,7 +29,7 @@ contract DVMTrader is DVMStorage { return receiveQuoteAmount; } - function sellQuote(address to) external returns (uint256 receiveBaseAmount) { + function sellQuote(address to) external isBuyAllow(to) returns (uint256 receiveBaseAmount) { uint256 quoteInput = _VAULT_.getQuoteInput(); uint256 mtFee; (receiveBaseAmount, mtFee) = querySellQuote(to, quoteInput); @@ -48,23 +48,37 @@ contract DVMTrader is DVMStorage { address call, bytes calldata data ) external { - (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); - uint256 B0 = calculateBase0(baseReserve, quoteReserve); - - uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(assetTo, quoteAmount); - uint256 baseMtFee = DecimalMath.mulCeil(baseAmount, mtFeeRate); - uint256 quoteMtFee = DecimalMath.mulCeil(quoteAmount, mtFeeRate); - - _VAULT_.transferBaseOut(_MAINTAINER_, baseMtFee); - _VAULT_.transferQuoteOut(_MAINTAINER_, quoteMtFee); _VAULT_.transferBaseOut(assetTo, baseAmount); _VAULT_.transferQuoteOut(assetTo, quoteAmount); - IExternalCall(call).DVMCall(data); + (uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve(); (uint256 baseBalance, uint256 quoteBalance) = _VAULT_.getVaultBalance(); - uint256 newB0 = calculateBase0(baseBalance, quoteBalance); - require(newB0 >= B0, "FLASH_LOAN_FAILED"); + + uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(assetTo); + uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(assetTo); + if (baseBalance < baseReserve) { + uint256 validBaseOut = DecimalMath.divCeil( + baseReserve - baseBalance, + DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate) + ); + baseBalance = baseReserve.sub(validBaseOut); + _VAULT_.transferBaseOut(_MAINTAINER_, DecimalMath.mulCeil(validBaseOut, mtFeeRate)); + } + if (quoteBalance < quoteReserve) { + uint256 validQuoteOut = DecimalMath.divCeil( + quoteReserve - quoteBalance, + DecimalMath.ONE.sub(mtFeeRate).sub(lpFeeRate) + ); + quoteBalance = quoteReserve.sub(validQuoteOut); + _VAULT_.transferQuoteOut(_MAINTAINER_, DecimalMath.mulCeil(validQuoteOut, mtFeeRate)); + } + + require( + calculateBase0(baseBalance, quoteBalance) >= calculateBase0(baseReserve, quoteReserve), + "FLASH_LOAN_FAILED" + ); + _VAULT_.sync(); } @@ -80,8 +94,8 @@ contract DVMTrader is DVMStorage { require(B0 >= B1, "DODO_BASE_BALANCE_NOT_ENOUGH"); uint256 Q = DODOMath._GeneralIntegrate(B0, B1, baseReserve, _I_, _K_); - uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader, Q); - uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader, Q); + uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader); + uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); mtFee = DecimalMath.mulCeil(Q, mtFeeRate); receiveQuoteAmount = Q.sub(mtFee).sub(DecimalMath.mulCeil(Q, lpFeeRate)); @@ -105,8 +119,8 @@ contract DVMTrader is DVMStorage { _K_ ); uint256 deltaBase = baseReserve.sub(newBaseReserve); - uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader, payQuoteAmount); - uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader, payQuoteAmount); + uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader); + uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader); mtFee = DecimalMath.mulCeil(deltaBase, mtFeeRate); receiveBaseAmount = deltaBase.sub(mtFee).sub(DecimalMath.mulCeil(deltaBase, lpFeeRate)); return (receiveBaseAmount, mtFee); diff --git a/contracts/DODOVendorMachine/impl/DVMVault.sol b/contracts/DODOVendorMachine/impl/DVMVault.sol index f68315d..cc256c8 100644 --- a/contracts/DODOVendorMachine/impl/DVMVault.sol +++ b/contracts/DODOVendorMachine/impl/DVMVault.sol @@ -110,11 +110,15 @@ contract DVMVault is InitializableOwnable { } function transferBaseOut(address to, uint256 amount) public onlyOwner { - IERC20(_BASE_TOKEN_).safeTransfer(to, amount); + if (amount > 0) { + IERC20(_BASE_TOKEN_).safeTransfer(to, amount); + } } function transferQuoteOut(address to, uint256 amount) public onlyOwner { - IERC20(_QUOTE_TOKEN_).safeTransfer(to, amount); + if (amount > 0) { + IERC20(_QUOTE_TOKEN_).safeTransfer(to, amount); + } } // Shares related diff --git a/contracts/DODOVendorMachine/intf/IDVM.sol b/contracts/DODOVendorMachine/intf/IDVM.sol index 8569973..854a6dd 100644 --- a/contracts/DODOVendorMachine/intf/IDVM.sol +++ b/contracts/DODOVendorMachine/intf/IDVM.sol @@ -16,7 +16,6 @@ interface IDVM { address lpFeeRateModel, address mtFeeRateModel, address tradePermissionManager, - address fundingPermissionManager, uint256 i, uint256 k ) external; diff --git a/contracts/Factory/DVMFactory.sol b/contracts/Factory/DVMFactory.sol index f67369f..1dd6414 100644 --- a/contracts/Factory/DVMFactory.sol +++ b/contracts/Factory/DVMFactory.sol @@ -59,7 +59,6 @@ contract DVMFactory is Ownable { createConstFeeRateModel(msg.sender, lpFeeRate), createConstFeeRateModel(msg.sender, mtFeeRate), createPermissionManager(msg.sender), - createPermissionManager(msg.sender), i, k ); diff --git a/contracts/intf/IFeeRateModel.sol b/contracts/intf/IFeeRateModel.sol index 10e7a30..076c316 100644 --- a/contracts/intf/IFeeRateModel.sol +++ b/contracts/intf/IFeeRateModel.sol @@ -9,5 +9,5 @@ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; interface IFeeRateModel { - function getFeeRate(address trader, uint256 amount) external view returns (uint256); + function getFeeRate(address trader) external view returns (uint256); } diff --git a/contracts/lib/ConstFeeRateModel.sol b/contracts/lib/ConstFeeRateModel.sol index 4cf695c..36d36ca 100644 --- a/contracts/lib/ConstFeeRateModel.sol +++ b/contracts/lib/ConstFeeRateModel.sol @@ -12,12 +12,10 @@ import {IFeeRateModel} from "../intf/IFeeRateModel.sol"; import {Ownable} from "../lib/Ownable.sol"; import {InitializableOwnable} from "../lib/InitializableOwnable.sol"; -interface IConstFeeRateModel { +interface IConstFeeRateModel is IFeeRateModel { function init(address owner, uint256 feeRate) external; function setFeeRate(uint256 newFeeRate) external; - - function getFeeRate(address, uint256) external view returns (uint256); } contract ConstFeeRateModel is InitializableOwnable, IFeeRateModel { @@ -32,7 +30,7 @@ contract ConstFeeRateModel is InitializableOwnable, IFeeRateModel { _FEE_RATE_ = newFeeRate; } - function getFeeRate(address, uint256) external override view returns (uint256) { + function getFeeRate(address) external override view returns (uint256) { return _FEE_RATE_; } }