flash loan
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user