flash loan

This commit is contained in:
mingda
2020-11-06 00:31:30 +08:00
parent f66a90d7b2
commit 81dc1c15a0
8 changed files with 65 additions and 39 deletions

View File

@@ -22,7 +22,6 @@ contract DVM is DVMTrader, DVMFunding {
address lpFeeRateModel, address lpFeeRateModel,
address mtFeeRateModel, address mtFeeRateModel,
address tradePermissionManager, address tradePermissionManager,
address fundingPermissionManager,
uint256 i, uint256 i,
uint256 k uint256 k
) external { ) external {
@@ -33,7 +32,6 @@ contract DVM is DVMTrader, DVMFunding {
_LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel); _LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel);
_MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel); _MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel);
_TRADE_PERMISSION_ = IPermissionManager(tradePermissionManager); _TRADE_PERMISSION_ = IPermissionManager(tradePermissionManager);
_FUNDING_PERMISSION_ = IPermissionManager(fundingPermissionManager);
_MAINTAINER_ = maintainer; _MAINTAINER_ = maintainer;
_I_ = i; _I_ = i;
_K_ = k; _K_ = k;

View File

@@ -22,16 +22,14 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard {
// ============ Variables for Control ============ // ============ Variables for Control ============
bool public _CLOSED_;
uint256 public _GAS_PRICE_LIMIT_; uint256 public _GAS_PRICE_LIMIT_;
// ============ Advanced Controls ============ // ============ Advanced Controls ============
bool public _BUYING_ALLOWED_; bool public _BUYING_CLOSE_;
bool public _SELLING_ALLOWED_; bool public _SELLING_CLOSE_;
IPermissionManager public _TRADE_PERMISSION_; IPermissionManager public _TRADE_PERMISSION_;
IPermissionManager public _FUNDING_PERMISSION_;
// ============ Core Address ============ // ============ Core Address ============
@@ -51,8 +49,16 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard {
// ============ Modifiers ============ // ============ Modifiers ============
modifier notClosed() { modifier isBuyAllow(address trader) {
require(!_CLOSED_, "DODO_CLOSED"); 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); _TRADE_PERMISSION_ = IPermissionManager(newTradePermissionManager);
} }
function setFundingPermissionManager(address newFundingPermissionManager) external onlyOwner {
_FUNDING_PERMISSION_ = IPermissionManager(newFundingPermissionManager);
}
function setMaintainer(address newMaintainer) external onlyOwner { function setMaintainer(address newMaintainer) external onlyOwner {
_MAINTAINER_ = newMaintainer; _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;
}
} }

View File

@@ -17,7 +17,7 @@ import {IExternalCall} from "../intf/IExternalCall.sol";
contract DVMTrader is DVMStorage { contract DVMTrader is DVMStorage {
using SafeMath for uint256; 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 baseInput = _VAULT_.getBaseInput();
uint256 mtFee; uint256 mtFee;
(receiveQuoteAmount, mtFee) = querySellBase(to, baseInput); (receiveQuoteAmount, mtFee) = querySellBase(to, baseInput);
@@ -29,7 +29,7 @@ contract DVMTrader is DVMStorage {
return receiveQuoteAmount; 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 quoteInput = _VAULT_.getQuoteInput();
uint256 mtFee; uint256 mtFee;
(receiveBaseAmount, mtFee) = querySellQuote(to, quoteInput); (receiveBaseAmount, mtFee) = querySellQuote(to, quoteInput);
@@ -48,23 +48,37 @@ contract DVMTrader is DVMStorage {
address call, address call,
bytes calldata data bytes calldata data
) external { ) 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_.transferBaseOut(assetTo, baseAmount);
_VAULT_.transferQuoteOut(assetTo, quoteAmount); _VAULT_.transferQuoteOut(assetTo, quoteAmount);
IExternalCall(call).DVMCall(data); IExternalCall(call).DVMCall(data);
(uint256 baseReserve, uint256 quoteReserve) = _VAULT_.getVaultReserve();
(uint256 baseBalance, uint256 quoteBalance) = _VAULT_.getVaultBalance(); (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(); _VAULT_.sync();
} }
@@ -80,8 +94,8 @@ contract DVMTrader is DVMStorage {
require(B0 >= B1, "DODO_BASE_BALANCE_NOT_ENOUGH"); require(B0 >= B1, "DODO_BASE_BALANCE_NOT_ENOUGH");
uint256 Q = DODOMath._GeneralIntegrate(B0, B1, baseReserve, _I_, _K_); uint256 Q = DODOMath._GeneralIntegrate(B0, B1, baseReserve, _I_, _K_);
uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader, Q); uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader);
uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader, Q); uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader);
mtFee = DecimalMath.mulCeil(Q, mtFeeRate); mtFee = DecimalMath.mulCeil(Q, mtFeeRate);
receiveQuoteAmount = Q.sub(mtFee).sub(DecimalMath.mulCeil(Q, lpFeeRate)); receiveQuoteAmount = Q.sub(mtFee).sub(DecimalMath.mulCeil(Q, lpFeeRate));
@@ -105,8 +119,8 @@ contract DVMTrader is DVMStorage {
_K_ _K_
); );
uint256 deltaBase = baseReserve.sub(newBaseReserve); uint256 deltaBase = baseReserve.sub(newBaseReserve);
uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader, payQuoteAmount); uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader);
uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader, payQuoteAmount); uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader);
mtFee = DecimalMath.mulCeil(deltaBase, mtFeeRate); mtFee = DecimalMath.mulCeil(deltaBase, mtFeeRate);
receiveBaseAmount = deltaBase.sub(mtFee).sub(DecimalMath.mulCeil(deltaBase, lpFeeRate)); receiveBaseAmount = deltaBase.sub(mtFee).sub(DecimalMath.mulCeil(deltaBase, lpFeeRate));
return (receiveBaseAmount, mtFee); return (receiveBaseAmount, mtFee);

View File

@@ -110,11 +110,15 @@ contract DVMVault is InitializableOwnable {
} }
function transferBaseOut(address to, uint256 amount) public onlyOwner { 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 { 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 // Shares related

View File

@@ -16,7 +16,6 @@ interface IDVM {
address lpFeeRateModel, address lpFeeRateModel,
address mtFeeRateModel, address mtFeeRateModel,
address tradePermissionManager, address tradePermissionManager,
address fundingPermissionManager,
uint256 i, uint256 i,
uint256 k uint256 k
) external; ) external;

View File

@@ -59,7 +59,6 @@ contract DVMFactory is Ownable {
createConstFeeRateModel(msg.sender, lpFeeRate), createConstFeeRateModel(msg.sender, lpFeeRate),
createConstFeeRateModel(msg.sender, mtFeeRate), createConstFeeRateModel(msg.sender, mtFeeRate),
createPermissionManager(msg.sender), createPermissionManager(msg.sender),
createPermissionManager(msg.sender),
i, i,
k k
); );

View File

@@ -9,5 +9,5 @@ pragma solidity 0.6.9;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
interface IFeeRateModel { interface IFeeRateModel {
function getFeeRate(address trader, uint256 amount) external view returns (uint256); function getFeeRate(address trader) external view returns (uint256);
} }

View File

@@ -12,12 +12,10 @@ import {IFeeRateModel} from "../intf/IFeeRateModel.sol";
import {Ownable} from "../lib/Ownable.sol"; import {Ownable} from "../lib/Ownable.sol";
import {InitializableOwnable} from "../lib/InitializableOwnable.sol"; import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
interface IConstFeeRateModel { interface IConstFeeRateModel is IFeeRateModel {
function init(address owner, uint256 feeRate) external; function init(address owner, uint256 feeRate) external;
function setFeeRate(uint256 newFeeRate) external; function setFeeRate(uint256 newFeeRate) external;
function getFeeRate(address, uint256) external view returns (uint256);
} }
contract ConstFeeRateModel is InitializableOwnable, IFeeRateModel { contract ConstFeeRateModel is InitializableOwnable, IFeeRateModel {
@@ -32,7 +30,7 @@ contract ConstFeeRateModel is InitializableOwnable, IFeeRateModel {
_FEE_RATE_ = newFeeRate; _FEE_RATE_ = newFeeRate;
} }
function getFeeRate(address, uint256) external override view returns (uint256) { function getFeeRate(address) external override view returns (uint256) {
return _FEE_RATE_; return _FEE_RATE_;
} }
} }