simplify dvm

This commit is contained in:
owen05
2020-12-30 12:23:52 +08:00
parent f08455e033
commit 4e5accd62d
19 changed files with 165 additions and 407 deletions

View File

@@ -101,11 +101,10 @@ contract CPFunding is CPStorage {
uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divCeil(baseDepth, poolQuote));
_poolI = ratio.mul(ratio).div(avgPrice);
}
_POOL_ = IDVMFactory(_POOL_FACTORY_).createUnOwnedDODOVendingMachine(
address(this),
_POOL_ = IDVMFactory(_POOL_FACTORY_).createDODOVendingMachine(
_poolBaseToken,
_poolQuoteToken,
3e15, // 0.3%
3e15, // 0.3% lp feeRate
_poolI,
DecimalMath.ONE
);

View File

@@ -9,8 +9,6 @@ pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import {IFeeRateModel} from "../../lib/FeeRateModel.sol";
import {IPermissionManager} from "../../lib/PermissionManager.sol";
import {IExternalValue} from "../../lib/ExternalValue.sol";
import {IERC20} from "../../intf/IERC20.sol";
import {DVMTrader} from "./DVMTrader.sol";
import {DVMFunding} from "./DVMFunding.sol";
@@ -18,19 +16,14 @@ import {DVMVault} from "./DVMVault.sol";
contract DVM is DVMTrader, DVMFunding {
function init(
address owner,
address maintainer,
address baseTokenAddress,
address quoteTokenAddress,
address lpFeeRateModel,
uint256 lpFeeRate,
address mtFeeRateModel,
address tradePermissionManager,
address gasPriceSource,
uint256 i,
uint256 k
) external {
initOwner(owner);
require(baseTokenAddress != quoteTokenAddress, "BASE_QUOTE_CAN_NOT_BE_SAME");
_BASE_TOKEN_ = IERC20(baseTokenAddress);
_QUOTE_TOKEN_ = IERC20(quoteTokenAddress);
@@ -41,10 +34,8 @@ contract DVM is DVMTrader, DVMFunding {
require(k <= 10**18);
_K_ = k;
_LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel);
_LP_FEE_RATE_ = lpFeeRate;
_MT_FEE_RATE_MODEL_ = IFeeRateModel(mtFeeRateModel);
_TRADE_PERMISSION_ = IPermissionManager(tradePermissionManager);
_GAS_PRICE_LIMIT_ = IExternalValue(gasPriceSource);
_MAINTAINER_ = maintainer;
string memory connect = "_";

View File

@@ -1,64 +0,0 @@
/*
Copyright 2020 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import {IDVM} from "../intf/IDVM.sol";
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
import {IExternalValue} from "../../lib/ExternalValue.sol";
contract DVMAdmin is InitializableOwnable {
address public _DVM_;
function init(address owner, address dvm) external {
initOwner(owner);
_DVM_ = dvm;
}
// function setLpFeeRateModel(address newLpFeeRateModel) external onlyOwner {
// IDVM(_DVM_).setLpFeeRateModel(newLpFeeRateModel);
// }
function setLpFeeRateValue(uint256 newLpFeeRate) external onlyOwner {
IDVM(_DVM_).setLpFeeRateValue(newLpFeeRate);
}
// function setMtFeeRateModel(address newMtFeeRateModel) external onlyOwner {
// IDVM(_DVM_).setMtFeeRateModel(newMtFeeRateModel);
// }
function setMtFeeRateValue(uint256 newMtFeeRate) external onlyOwner {
IDVM(_DVM_).setMtFeeRateValue(newMtFeeRate);
}
// function setTradePermissionManager(address newTradePermissionManager) external onlyOwner {
// IDVM(_DVM_).setTradePermissionManager(newTradePermissionManager);
// }
function setMaintainer(address newMaintainer) external onlyOwner {
IDVM(_DVM_).setMaintainer(newMaintainer);
}
// function setGasPriceSource(address newGasPriceLimitSource) external onlyOwner {
// IDVM(_DVM_).setGasPriceSource(newGasPriceLimitSource);
// }
function setBuy(bool open) external onlyOwner {
IDVM(_DVM_).setBuy(open);
}
function setSell(bool open) external onlyOwner {
IDVM(_DVM_).setSell(open);
}
// ============ Admin Version Control ============
function version() external pure returns (string memory) {
return "DVMAdmin 1.0.0"; // 1.0.0
}
}

View File

@@ -58,7 +58,7 @@ contract DVMFunding is DVMVault {
shares = DecimalMath.mulFloor(totalSupply, mintRatio);
}
_mint(to, shares);
_sync();
_setReserve(baseBalance, quoteBalance);
emit BuyShares(to, shares, _SHARES_[to]);
}

View File

@@ -8,27 +8,16 @@
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
import {InitializableOwnable} from "../../lib/InitializableOwnable.sol";
import {ReentrancyGuard} from "../../lib/ReentrancyGuard.sol";
import {SafeMath} from "../../lib/SafeMath.sol";
import {DODOMath} from "../../lib/DODOMath.sol";
import {DecimalMath} from "../../lib/DecimalMath.sol";
import {IPermissionManager} from "../../lib/PermissionManager.sol";
import {IExternalValue} from "../../lib/ExternalValue.sol";
import {IFeeRateModel} from "../../lib/FeeRateModel.sol";
import {IERC20} from "../../intf/IERC20.sol";
contract DVMStorage is InitializableOwnable, ReentrancyGuard {
contract DVMStorage is ReentrancyGuard {
using SafeMath for uint256;
// ============ Advanced Controls ============
bool public _BUYING_CLOSE_;
bool public _SELLING_CLOSE_;
IPermissionManager public _TRADE_PERMISSION_;
IExternalValue public _GAS_PRICE_LIMIT_;
// ============ Core Address ============
address public _MAINTAINER_;
@@ -36,8 +25,8 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard {
IERC20 public _BASE_TOKEN_;
IERC20 public _QUOTE_TOKEN_;
uint256 public _BASE_RESERVE_;
uint256 public _QUOTE_RESERVE_;
uint128 public _BASE_RESERVE_;
uint128 public _QUOTE_RESERVE_;
// ============ Shares (ERC20) ============
@@ -53,81 +42,13 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard {
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32
public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint256) public nonces;
// ============ Variables for Pricing ============
IFeeRateModel public _LP_FEE_RATE_MODEL_;
uint256 public _LP_FEE_RATE_;
IFeeRateModel public _MT_FEE_RATE_MODEL_;
uint256 public _K_;
uint256 public _I_;
// ============ Events ============
event SetLpFeeRateModel(address oldAddr, address newAddr);
event SetMtFeeRateModel(address oldAddr, address newAddr);
event SetTradePermissionManager(address oldAddr, address newAddr);
event SetMaintainer(address oldAddr, address newAddr);
event SetGasPriceSource(address oldAddr, address newAddr);
event SetBuy(bool allow);
event SetSell(bool allow);
event SetLpFeeRate(uint256 newValue);
event SetMtFeeRate(uint256 newValue);
// ============ Setting Functions ============
function setLpFeeRateModel(address newLpFeeRateModel) external onlyOwner {
emit SetLpFeeRateModel(address(_LP_FEE_RATE_MODEL_), newLpFeeRateModel);
_LP_FEE_RATE_MODEL_ = IFeeRateModel(newLpFeeRateModel);
}
function setMtFeeRateModel(address newMtFeeRateModel) external onlyOwner {
emit SetMtFeeRateModel(address(_MT_FEE_RATE_MODEL_), newMtFeeRateModel);
_MT_FEE_RATE_MODEL_ = IFeeRateModel(newMtFeeRateModel);
}
function setLpFeeRateValue(uint256 newLpFeeRate) external onlyOwner {
_LP_FEE_RATE_MODEL_.setFeeRate(newLpFeeRate);
emit SetLpFeeRate(newLpFeeRate);
}
function setMtFeeRateValue(uint256 newMtFeeRate) external onlyOwner {
_MT_FEE_RATE_MODEL_.setFeeRate(newMtFeeRate);
emit SetMtFeeRate(newMtFeeRate);
}
function setTradePermissionManager(address newTradePermissionManager) external onlyOwner {
emit SetTradePermissionManager(address(_TRADE_PERMISSION_), newTradePermissionManager);
_TRADE_PERMISSION_ = IPermissionManager(newTradePermissionManager);
}
function setMaintainer(address newMaintainer) external onlyOwner {
emit SetMaintainer(address(_MAINTAINER_), newMaintainer);
_MAINTAINER_ = newMaintainer;
}
function setGasPriceSource(address newGasPriceLimitSource) external onlyOwner {
emit SetGasPriceSource(address(_GAS_PRICE_LIMIT_), newGasPriceLimitSource);
_GAS_PRICE_LIMIT_ = IExternalValue(newGasPriceLimitSource);
}
function setBuy(bool open) external onlyOwner {
emit SetBuy(open);
_BUYING_CLOSE_ = !open;
}
function setSell(bool open) external onlyOwner {
emit SetSell(open);
_SELLING_CLOSE_ = !open;
}
}

View File

@@ -35,42 +35,21 @@ contract DVMTrader is DVMVault {
uint256 quoteAmount
);
// ============ Modifiers ============
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"
);
_;
}
modifier limitGasPrice() {
require(tx.gasprice <= _GAS_PRICE_LIMIT_.get(), "GAS_PRICE_EXCEED");
_;
}
// ============ Execute ============
function sellBase(address to)
external
preventReentrant
limitGasPrice
isSellAllow(to) // set DVM address in trade permission
returns (uint256 receiveQuoteAmount)
{
uint256 baseInput = getBaseInput();
uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this));
uint256 baseInput = baseBalance.sub(uint256(_BASE_RESERVE_));
uint256 mtFee;
(receiveQuoteAmount, mtFee) = querySellBase(tx.origin, baseInput);
_transferQuoteOut(to, receiveQuoteAmount);
_transferQuoteOut(_MAINTAINER_, mtFee);
_sync();
_setReserve(baseBalance, _QUOTE_TOKEN_.balanceOf(address(this)));
emit DODOSwap(
address(_BASE_TOKEN_),
@@ -84,17 +63,16 @@ contract DVMTrader is DVMVault {
function sellQuote(address to)
external
preventReentrant
limitGasPrice
isBuyAllow(to)
returns (uint256 receiveBaseAmount)
{
uint256 quoteInput = getQuoteInput();
uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));
uint256 quoteInput = quoteBalance.sub(uint256(_QUOTE_RESERVE_));
uint256 mtFee;
(receiveBaseAmount, mtFee) = querySellQuote(tx.origin, quoteInput);
_transferBaseOut(to, receiveBaseAmount);
_transferBaseOut(_MAINTAINER_, mtFee);
_sync();
_setReserve(_BASE_TOKEN_.balanceOf(address(this)), quoteBalance);
emit DODOSwap(
address(_QUOTE_TOKEN_),
@@ -110,7 +88,7 @@ contract DVMTrader is DVMVault {
uint256 quoteAmount,
address assetTo,
bytes calldata data
) external preventReentrant isSellAllow(assetTo) isBuyAllow(assetTo) {
) external preventReentrant {
_transferBaseOut(assetTo, baseAmount);
_transferQuoteOut(assetTo, quoteAmount);
@@ -128,9 +106,9 @@ contract DVMTrader is DVMVault {
// sell quote
if (baseBalance < _BASE_RESERVE_) {
uint256 quoteInput = quoteBalance.sub(_QUOTE_RESERVE_);
uint256 quoteInput = quoteBalance.sub(uint256(_QUOTE_RESERVE_));
(uint256 receiveBaseAmount, uint256 mtFee) = querySellQuote(tx.origin, quoteInput);
require(_BASE_RESERVE_.sub(baseBalance) <= receiveBaseAmount, "FLASH_LOAN_FAILED");
require(uint256(_BASE_RESERVE_).sub(baseBalance) <= receiveBaseAmount, "FLASH_LOAN_FAILED");
_transferBaseOut(_MAINTAINER_, mtFee);
emit DODOSwap(
@@ -138,15 +116,15 @@ contract DVMTrader is DVMVault {
address(_BASE_TOKEN_),
quoteInput,
receiveBaseAmount,
tx.origin
msg.sender
);
}
// sell base
if (quoteBalance < _QUOTE_RESERVE_) {
uint256 baseInput = baseBalance.sub(_BASE_RESERVE_);
uint256 baseInput = baseBalance.sub(uint256(_BASE_RESERVE_));
(uint256 receiveQuoteAmount, uint256 mtFee) = querySellBase(tx.origin, baseInput);
require(_QUOTE_RESERVE_.sub(quoteBalance) <= receiveQuoteAmount, "FLASH_LOAN_FAILED");
require(uint256(_QUOTE_RESERVE_).sub(quoteBalance) <= receiveQuoteAmount, "FLASH_LOAN_FAILED");
_transferQuoteOut(_MAINTAINER_, mtFee);
emit DODOSwap(
@@ -172,11 +150,10 @@ contract DVMTrader is DVMVault {
{
(receiveQuoteAmount, ) = PMMPricing.sellBaseToken(getPMMState(), payBaseAmount);
uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader);
uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader);
mtFee = DecimalMath.mulFloor(receiveQuoteAmount, mtFeeRate);
receiveQuoteAmount = receiveQuoteAmount
.sub(DecimalMath.mulFloor(receiveQuoteAmount, lpFeeRate))
.sub(DecimalMath.mulFloor(receiveQuoteAmount, _LP_FEE_RATE_))
.sub(mtFee);
}
@@ -187,11 +164,10 @@ contract DVMTrader is DVMVault {
{
(receiveBaseAmount, ) = PMMPricing.sellQuoteToken(getPMMState(), payQuoteAmount);
uint256 lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(trader);
uint256 mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(trader);
mtFee = DecimalMath.mulFloor(receiveBaseAmount, mtFeeRate);
receiveBaseAmount = receiveBaseAmount
.sub(DecimalMath.mulFloor(receiveBaseAmount, lpFeeRate))
.sub(DecimalMath.mulFloor(receiveBaseAmount, _LP_FEE_RATE_))
.sub(mtFee);
}

View File

@@ -36,15 +36,10 @@ contract DVMVault is DVMStorage {
}
function getUserFeeRate(address user) external view returns (uint256 lpFeeRate, uint256 mtFeeRate) {
lpFeeRate = _LP_FEE_RATE_MODEL_.getFeeRate(user);
lpFeeRate = _LP_FEE_RATE_;
mtFeeRate = _MT_FEE_RATE_MODEL_.getFeeRate(user);
}
function getUserTradePermission(address user) external view returns (bool isBuyAllow, bool isSellAllow) {
isBuyAllow = (!_BUYING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(user));
isSellAllow = (!_SELLING_CLOSE_ && _TRADE_PERMISSION_.isAllowed(user));
}
// ============ Asset In ============
function getBaseInput() public view returns (uint256 input) {
@@ -57,14 +52,21 @@ contract DVMVault is DVMStorage {
// ============ Set States ============
function _setReserve(uint256 baseReserve, uint256 quoteReserve) internal {
require(baseReserve <= uint128(-1) && quoteReserve <= uint128(-1), "OVERFLOW");
_BASE_RESERVE_ = uint128(baseReserve);
_QUOTE_RESERVE_ = uint128(quoteReserve);
}
function _sync() internal {
uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this));
uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this));
require(baseBalance <= uint128(-1) && quoteBalance <= uint128(-1), "OVERFLOW");
if (baseBalance != _BASE_RESERVE_) {
_BASE_RESERVE_ = baseBalance;
_BASE_RESERVE_ = uint128(baseBalance);
}
if (quoteBalance != _QUOTE_RESERVE_) {
_QUOTE_RESERVE_ = quoteBalance;
_QUOTE_RESERVE_ = uint128(quoteBalance);
}
}

View File

@@ -10,14 +10,11 @@ pragma experimental ABIEncoderV2;
interface IDVM {
function init(
address owner,
address maintainer,
address baseTokenAddress,
address quoteTokenAddress,
address lpFeeRateModel,
uint256 lpFeeRate,
address mtFeeRateModel,
address tradePermissionManager,
address gasPriceSource,
uint256 i,
uint256 k
) external;
@@ -26,8 +23,6 @@ interface IDVM {
function _QUOTE_TOKEN_() external returns (address);
function _LP_FEE_RATE_MODEL_() external returns (address);
function _MT_FEE_RATE_MODEL_() external returns (address);
function getVaultReserve() external returns (uint256 baseReserve, uint256 quoteReserve);
@@ -38,23 +33,4 @@ interface IDVM {
function buyShares(address to) external returns (uint256);
//=========== admin ==========
function setLpFeeRateModel(address newLpFeeRateModel) external;
function setLpFeeRateValue(uint256 newLpFeeRate) external;
function setMtFeeRateModel(address newMtFeeRateModel) external;
function setMtFeeRateValue(uint256 newMtFeeRate) external;
function setTradePermissionManager(address newTradePermissionManager) external;
function setMaintainer(address newMaintainer) external;
function setGasPriceSource(address newGasPriceLimitSource) external;
function setBuy(bool open) external;
function setSell(bool open) external;
//==============================
}

View File

@@ -1,13 +0,0 @@
/*
Copyright 2020 DODO ZOO.
SPDX-License-Identifier: Apache-2.0
*/
pragma solidity 0.6.9;
pragma experimental ABIEncoderV2;
interface IDVMAdmin {
function init(address owner, address _dvm) external;
}

View File

@@ -10,24 +10,10 @@ pragma experimental ABIEncoderV2;
import {InitializableOwnable} from "../lib/InitializableOwnable.sol";
import {ICloneFactory} from "../lib/CloneFactory.sol";
import {IFeeRateModel} from "../lib/FeeRateModel.sol";
import {IDVM} from "../DODOVendingMachine/intf/IDVM.sol";
import {IDVMAdmin} from "../DODOVendingMachine/intf/IDVMAdmin.sol";
import {IPermissionManager} from "../lib/PermissionManager.sol";
interface IDVMFactory {
function createDODOVendingMachine(
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 mtFeeRate,
uint256 i,
uint256 k
) external returns (address newVendingMachine);
function createUnOwnedDODOVendingMachine(
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
@@ -41,16 +27,8 @@ contract DVMFactory is InitializableOwnable {
address public immutable _CLONE_FACTORY_;
address public immutable _DVM_TEMPLATE_;
address public immutable _FEE_RATE_MODEL_TEMPLATE_;
address public immutable _PERMISSION_MANAGER_TEMPLATE_;
address public _DVM_ADMIN_TEMPLATE_;
address public immutable _DEFAULT_MAINTAINER_;
address public immutable _DEFAULT_MT_FEE_RATE_MODEL_;
address public immutable _DEFAULT_PERMISSION_MANAGER_;
address public immutable _DEFAULT_GAS_PRICE_SOURCE_;
address internal constant _EMPTY_ = 0x0000000000000000000000000000000000000000;
// ============ Registry ============
@@ -75,59 +53,16 @@ contract DVMFactory is InitializableOwnable {
constructor(
address cloneFactory,
address dvmTemplate,
address dvmAdminTemplate,
address feeRateModelTemplate,
address permissionManagerTemplate,
address defaultGasPriceSource,
address defaultMaintainer,
address defaultMtFeeRateModel,
address defaultPermissionManager
address defaultMtFeeRateModel
) public {
_CLONE_FACTORY_ = cloneFactory;
_DVM_TEMPLATE_ = dvmTemplate;
_DVM_ADMIN_TEMPLATE_ = dvmAdminTemplate;
_FEE_RATE_MODEL_TEMPLATE_ = feeRateModelTemplate;
_PERMISSION_MANAGER_TEMPLATE_ = permissionManagerTemplate;
_DEFAULT_MAINTAINER_ = defaultMaintainer;
_DEFAULT_MT_FEE_RATE_MODEL_ = defaultMtFeeRateModel;
_DEFAULT_PERMISSION_MANAGER_ = defaultPermissionManager;
_DEFAULT_GAS_PRICE_SOURCE_ = defaultGasPriceSource;
}
function createDODOVendingMachine(
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 mtFeeRate,
uint256 i,
uint256 k
) external returns (address newVendingMachine) {
newVendingMachine = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_);
{
address adminModel = _createDVMAdminModel(creator, newVendingMachine);
IDVM(newVendingMachine).init(
adminModel,
creator,
baseToken,
quoteToken,
_createFeeRateModel(adminModel, lpFeeRate),
_createFeeRateModel(adminModel, mtFeeRate),
_createPermissionManager(adminModel),
_DEFAULT_GAS_PRICE_SOURCE_,
i,
k
);
}
_REGISTRY_[baseToken][quoteToken].push(newVendingMachine);
_USER_REGISTRY_[creator].push(newVendingMachine);
emit NewDVM(baseToken, quoteToken, creator, newVendingMachine);
}
function createUnOwnedDODOVendingMachine(
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
@@ -137,49 +72,21 @@ contract DVMFactory is InitializableOwnable {
newVendingMachine = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_);
{
IDVM(newVendingMachine).init(
_EMPTY_,
_DEFAULT_MAINTAINER_,
baseToken,
quoteToken,
_createFeeRateModel(_EMPTY_, lpFeeRate),
lpFeeRate,
_DEFAULT_MT_FEE_RATE_MODEL_,
_DEFAULT_PERMISSION_MANAGER_,
_DEFAULT_GAS_PRICE_SOURCE_,
i,
k
);
}
_REGISTRY_[baseToken][quoteToken].push(newVendingMachine);
_USER_REGISTRY_[creator].push(newVendingMachine);
emit NewDVM(baseToken, quoteToken, creator, newVendingMachine);
}
function _createFeeRateModel(address owner, uint256 feeRate)
internal
returns (address feeRateModel)
{
feeRateModel = ICloneFactory(_CLONE_FACTORY_).clone(_FEE_RATE_MODEL_TEMPLATE_);
IFeeRateModel(feeRateModel).init(owner, feeRate);
}
function _createPermissionManager(address owner) internal returns (address permissionManager) {
permissionManager = ICloneFactory(_CLONE_FACTORY_).clone(_PERMISSION_MANAGER_TEMPLATE_);
IPermissionManager(permissionManager).initOwner(owner);
}
function _createDVMAdminModel(address owner, address dvm)
internal
returns (address adminModel)
{
adminModel = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_ADMIN_TEMPLATE_);
IDVMAdmin(adminModel).init(owner, dvm);
_USER_REGISTRY_[msg.sender].push(newVendingMachine);
emit NewDVM(baseToken, quoteToken, msg.sender, newVendingMachine);
}
// ============ Admin Operation Functions ============
function updateAdminTemplate(address _newDVMAdminTemplate) external onlyOwner {
_DVM_ADMIN_TEMPLATE_ = _newDVMAdminTemplate;
}
function addPoolByAdmin(
address creator,

View File

@@ -45,7 +45,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
address sender,
uint256 fromAmount,
uint256 returnAmount,
uint8 sourceFlag
uint256 sourceFlag
);
// ============ Modifiers ============
@@ -92,7 +92,6 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
uint256 baseInAmount,
uint256 quoteInAmount,
uint256 lpFeeRate,
uint256 mtFeeRate,
uint256 i,
uint256 k,
uint256 deadLine
@@ -108,11 +107,9 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
address _baseToken = baseToken == _ETH_ADDRESS_ ? _WETH_ : baseToken;
address _quoteToken = quoteToken == _ETH_ADDRESS_ ? _WETH_ : quoteToken;
newVendingMachine = IDODOV2(_DVM_FACTORY_).createDODOVendingMachine(
msg.sender,
_baseToken,
_quoteToken,
lpFeeRate,
mtFeeRate,
i,
k
);
@@ -303,7 +300,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
address toToken,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
)
external
@@ -312,7 +309,6 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
judgeExpired(deadLine)
returns (uint256 returnAmount)
{
require(dodoPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH");
uint256 originToTokenBalance = IERC20(toToken).balanceOf(msg.sender);
IWETH(_WETH_).deposit{value: msg.value}();
@@ -320,18 +316,19 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
for (uint256 i = 0; i < dodoPairs.length; i++) {
if (i == dodoPairs.length - 1) {
if (directions[i] == 0) {
if (directions & 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(assetTo);
} else {
IDODOV2(dodoPairs[i]).sellQuote(assetTo);
}
} else {
if (directions[i] == 0) {
if (directions & 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(dodoPairs[i + 1]);
} else {
IDODOV2(dodoPairs[i]).sellQuote(dodoPairs[i + 1]);
}
}
directions = directions >> 1;
}
returnAmount = IERC20(toToken).balanceOf(msg.sender).sub(originToTokenBalance);
@@ -352,7 +349,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
uint256 fromTokenAmount,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
)
external
@@ -360,23 +357,23 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
judgeExpired(deadLine)
returns (uint256 returnAmount)
{
require(dodoPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH");
IDODOApprove(_DODO_APPROVE_).claimTokens(fromToken, msg.sender, dodoPairs[0], fromTokenAmount);
for (uint256 i = 0; i < dodoPairs.length; i++) {
if (i == dodoPairs.length - 1) {
if (directions[i] == 0) {
if (directions & 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(address(this));
} else {
IDODOV2(dodoPairs[i]).sellQuote(address(this));
}
} else {
if (directions[i] == 0) {
if (directions & 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(dodoPairs[i + 1]);
} else {
IDODOV2(dodoPairs[i]).sellQuote(dodoPairs[i + 1]);
}
}
directions = directions >> 1;
}
returnAmount = IWETH(_WETH_).balanceOf(address(this));
require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough");
@@ -399,7 +396,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
uint256 fromTokenAmount,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
)
external
@@ -407,24 +404,24 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable
judgeExpired(deadLine)
returns (uint256 returnAmount)
{
require(dodoPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH");
uint256 originToTokenBalance = IERC20(toToken).balanceOf(msg.sender);
IDODOApprove(_DODO_APPROVE_).claimTokens(fromToken, msg.sender, dodoPairs[0], fromTokenAmount);
for (uint256 i = 0; i < dodoPairs.length; i++) {
if (i == dodoPairs.length - 1) {
if (directions[i] == 0) {
if (directions & 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(assetTo);
} else {
IDODOV2(dodoPairs[i]).sellQuote(assetTo);
}
} else {
if (directions[i] == 0) {
if (directions& 1 == 0) {
IDODOV2(dodoPairs[i]).sellBase(dodoPairs[i + 1]);
} else {
IDODOV2(dodoPairs[i]).sellQuote(dodoPairs[i + 1]);
}
}
directions = directions >> 1;
}
returnAmount = IERC20(toToken).balanceOf(msg.sender).sub(originToTokenBalance);
require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough");

View File

@@ -26,6 +26,7 @@ contract DODOV2RouteHelper {
uint256 mtFeeRate;
address baseToken;
address quoteToken;
address curPair;
}
constructor(address dvmFactory,address dppFactory) public {
@@ -39,7 +40,7 @@ contract DODOV2RouteHelper {
uint256 len = baseToken0DVM.length + baseToken1DVM.length + baseToken0DPP.length + baseToken1DPP.length;
res = new PairDetail[](len);
for(uint8 i = 0; i < len; i++) {
PairDetail memory curRes = PairDetail(0,0,0,0,0,0,0,0,0,address(0),address(0));
PairDetail memory curRes = PairDetail(0,0,0,0,0,0,0,0,0,address(0),address(0),address(0));
address cur;
if(i < baseToken0DVM.length) {
cur = baseToken0DVM[i];
@@ -72,7 +73,7 @@ contract DODOV2RouteHelper {
(curRes.lpFeeRate, curRes.mtFeeRate) = IDODOV2(cur).getUserFeeRate(userAddr);
}
curRes.curPair = cur;
res[i] = curRes;
}
}

View File

@@ -43,11 +43,9 @@ interface IDODOV2 {
//========== DODOVendingMachine ========
function createDODOVendingMachine(
address creator,
address baseToken,
address quoteToken,
uint256 lpFeeRate,
uint256 mtFeeRate,
uint256 i,
uint256 k
) external returns (address newVendingMachine);

View File

@@ -16,7 +16,7 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 {
address toToken,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
) external payable returns (uint256 returnAmount);
@@ -26,7 +26,7 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 {
uint256 fromTokenAmount,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
) external returns (uint256 returnAmount);
@@ -37,7 +37,7 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 {
uint256 fromTokenAmount,
uint256 minReturnAmount,
address[] memory dodoPairs,
uint8[] memory directions,
uint256 directions,
uint256 deadLine
) external returns (uint256 returnAmount);
@@ -48,7 +48,6 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 {
uint256 baseInAmount,
uint256 quoteInAmount,
uint256 lpFeeRate,
uint256 mtFeeRate,
uint256 i,
uint256 k,
uint256 deadLine

View File

@@ -151,3 +151,21 @@ DODOV2RouteHelper Address: 0x3249f48a507588740d291c154a6b607521e4cDED
DODOProxyV2 Address: 0xd5C27770E8e2F43B959484971472a0019b17fA56
Init DODOProxyV2 Tx: 0xdb70bb4355e71060803df0fb9833e03a4e4e657af2afbf1e732cf996614ca8c2
DODOApprove Init tx: 0x10e6bc3c71ac60145c599acbcfeb7571173445b02756a7d98c7d4e6dbe6f4ecd
====================================================
network type: kovan
Deploy time: 2020/12/29 上午11:08:34
Deploy type: HELPER V2
DODOV2RouteHelper Address: 0x3aAfE7c2643807718EFE35D6D529A74255cA4319
====================================================
network type: kovan
Deploy time: 2020/12/29 下午3:32:59
Deploy type: HELPER V2
DODOV2RouteHelper Address: 0x3579B9f85B83C06B227CAAe5F22fC05afA223552
====================================================
network type: kovan
Deploy time: 2020/12/29 下午3:33:16
Deploy type: V2
DODOApprove Address: 0xeEA9F08eBfde6915AB1C0051F3eB2612DbA95d5D
DODOProxyV2 Address: 0x97B779AD504bbd5b1BFB50e57584a876Dc65171a
Init DODOProxyV2 Tx: 0xd04c400fb46a0dd1e30ac04e9bce3e353869ffcb8ab7de622e2a936a3344d7b0
DODOApprove Init tx: 0xa78fe0b42e29489c1395e4574531902e1bc7348268bb102b001e4f3ffd47e83a

View File

@@ -234,3 +234,24 @@ network type: kovan
Deploy time: 2020/12/24 下午4:35:40
Mock SWAP Tx: V2
Swap Tx:0x3adcb6a34a7c86d62f9aca1b9448b0c66092bd8bab535361972bf564090a8124
====================================================
network type: kovan
Deploy time: 2020/12/27 下午10:19:11
Manual add Pool: V2
Manual add Pool Tx:0x51268996e829f32fad92ffc3bb21174768c706975d5536de288febfe33777c61
====================================================
network type: kovan
Deploy time: 2020/12/30 上午9:41:36
Mock POOL Tx: V2
Approve:0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE Tx: 0x90ebcdcd94428d2fe932403f283de1a428367b24eb3d717e3c9ae8cbc7fa042d
Approve:0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA Tx: 0xf10510050a3e6f9672f0bbffa878f78157760813c855d0737a5e7dbcef1f8bdf
Approve:0xFE1133ea03d701C5006b7f065bBf987955E7A67C Tx: 0x15a3ce08afbfc3a0a76523475b8a046a513e60e6d53206c13a008a06f657e93e
Approve:0x123ee47BaE3F64d422F2FB18ac444B47c1880F4C Tx: 0x2b35aececc77bf35713e763346dcc34f0bc157b8f11801fc00be67f370eadf5e
Approve:0x0ab8EF8B19655F32959c83e5fC5cD6536065D28f Tx: 0xd7f5086c4d84e2a8b0d7770b1806e93769556c0157d3deebf2b1230f94cf062a
Approve:0x6462794c19e6b4543BEC56200212c7c746bbB9eB Tx: 0x15f9224529d0a83664a31b4c0c98782e4921fed15cb2b7e58c2cc72c74bdb2fd
Approve:0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e Tx: 0x790a3da25ad80e53ce5235a8c0654f223ae0138e2fa7eccb23b9ea758475ee17
Approve:0x156595bAF85D5C29E91d959889B022d952190A64 Tx: 0xc658ad431fe8c48237d692a05219987de5e9fdbbfe2f5fce121af0b239f6b8b2
Create DVM: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0xD1577E3e27dab80D5F4a11Fe0960526418267e8f Tx: 0x6060ffc9b8175f19713d574127e79de60587671782dee3f40365976bc62e3e2b
Create DVM: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0xF2A7675f42F286214550c76c02D79efAd4A6D7ce Tx: 0xd6605ad6f00b8f01d2d0514e833dd1b559550cc9c61d90056930f9ca48d07f65
Create DPP: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0x50CA4A1714bE260B8aB8980c1649943b392d1cDf Tx: 0x8308da29d498548347380e73ad2daab06b4950db2d6e5e4766d858b4eea50eed
Create DPP: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0x2f487299a7f5aEe132348dC306b51816F4af17c2 Tx: 0x02fab2ac1c39494536d78004dd9de93e20609ea9a61f9aa9d1ddc1b0554071b2

View File

@@ -66,7 +66,7 @@ module.exports = async (deployer, network, accounts) => {
WETHAddress = "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b";
chiAddress = "0x0000000000004946c0e9f43f4dee607b0ef1fa1c";
DODOCalleeHelperAddress = "0x507EBbb195CF54E0aF147A2b269C08a38EA36989";
DODORouteV2HelperAddress = "";
DODORouteV2HelperAddress = "0x3aAfE7c2643807718EFE35D6D529A74255cA4319";
//Template
CloneFactoryAddress = "0xf7959fe661124C49F96CF30Da33729201aEE1b27";
FeeRateModelTemplateAddress = "0xEF3137780B387313c5889B999D03BdCf9aeEa892";
@@ -78,15 +78,15 @@ module.exports = async (deployer, network, accounts) => {
DefaultMtFeeRateAddress = "0xEfdE4225AC747136289979e29f1236527b2E4DB1";
DefaultPermissionAddress = "0xACc7E23368261e1E02103c4e5ae672E7D01f5797";
DvmTemplateAddress = "";
DvmTemplateAddress = "0x9d37C6BB2e3D62263099faAF2940C0De67a4FD6F";
DvmAdminTemplateAddress = "0x45f455d7E233403F10b7AFCB0d0d0c0d775AFf63";
DppTemplateAddress = "";
DppTemplateAddress = "0x75CC454c9771A7f1AF4848C4c3775C98b601563E";
DppAdminTemplateAddress = "0xDfdd9e1693C3A6AF25307c9dA561021f9e685878";
CpTemplateAddress = "";
CpTemplateAddress = "0x60580b981f2670C872AF0119b21C6596Ad7C5D51";
//Factory
DvmFactoryAddress = "";
DppFactoryAddress = "";
CpFactoryAddress = "";
DvmFactoryAddress = "0xF2a62693FB14b326C3719e5aeEF28e8e66dC954e";
DppFactoryAddress = "0x58Bc8D248AcbE95CE29CF893C6666D58AF92d941";
CpFactoryAddress = "0xD2d3c70C75E4Bb10eE366C8f54A06cCdDF5F3906";
//Approve
DODOApproveAddress = "";
//Account
@@ -163,7 +163,7 @@ module.exports = async (deployer, network, accounts) => {
logger.log("Deploy time: " + new Date().toLocaleString());
logger.log("Deploy type: HELPER V2");
await deployer.deploy(DODOV2RouteHelper, "0x6cbAE38DF513356878cF8e859A33E0eA92BfE023","0x92fE64e923d3B2A2479fACfFF7DAE8a3056Dc4E1");
await deployer.deploy(DODOV2RouteHelper, "0xF2a62693FB14b326C3719e5aeEF28e8e66dC954e","0x58Bc8D248AcbE95CE29CF893C6666D58AF92d941");
DODOV2RouteHelperAddress = DODOV2RouteHelper.address;
logger.log("DODOV2RouteHelper Address: ", DODOV2RouteHelperAddress);
}

View File

@@ -13,38 +13,54 @@ const DVMFactory = artifacts.require("DVMFactory");
const DPPFactory = artifacts.require("DPPFactory");
const POOL_PARAM = [
// {
// baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0
// quoteAddr: "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e", //USDC
// lpFeeRate: "3000000000000000", //0.003
// mtFeeRate: "1000000000000000", //0.001
// i: "10000000", //10
// k: "500000000000000000" //0.5
// },
// {
// baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0
// quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT
// lpFeeRate: "3000000000000000", //0.003
// mtFeeRate: "1000000000000000", //0.001
// i: "10000000", //10
// k: "0" //0
// },
// {
// baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1
// quoteAddr: "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e", //USDC
// lpFeeRate: "3000000000000000", //0.003
// mtFeeRate: "1000000000000000", //0.001
// i: "5000000", //5
// k: "1000000000000000000" //1
// },
// {
// baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1
// quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT
// lpFeeRate: "3000000000000000", //0.003
// mtFeeRate: "1000000000000000", //0.001
// i: "8000000", //8
// k: "900000000000000000" //0.9
// },
{
baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0
quoteAddr: "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e", //USDC
quoteAddr: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH
lpFeeRate: "3000000000000000", //0.003
mtFeeRate: "1000000000000000", //0.001
i: "10000000", //10
k: "500000000000000000" //0.5
},
{
baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0
quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT
lpFeeRate: "3000000000000000", //0.003
mtFeeRate: "1000000000000000", //0.001
i: "10000000", //10
k: "0" //0
i: "45000000000000000000", //45
k: "800000000000000000" //0.8
},
{
baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1
quoteAddr: "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e", //USDC
quoteAddr: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH
lpFeeRate: "3000000000000000", //0.003
mtFeeRate: "1000000000000000", //0.001
i: "5000000", //5
k: "1000000000000000000" //1
i: "30000000000000000000", //30
k: "300000000000000000" //0.3
},
{
baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1
quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT
lpFeeRate: "3000000000000000", //0.003
mtFeeRate: "1000000000000000", //0.001
i: "8000000", //8
k: "900000000000000000" //0.9
}
];
module.exports = async (deployer, network, accounts) => {
@@ -56,8 +72,8 @@ module.exports = async (deployer, network, accounts) => {
let DPPFactoryAddress = "0x58Bc8D248AcbE95CE29CF893C6666D58AF92d941";
let DVMFactoryAddress = "0xF2a62693FB14b326C3719e5aeEF28e8e66dC954e";
let DODOApproveAddress = "0x9F332B3a07536A2b0caaB3E3b9D2a5dFD6173c6c";
let DODOProxyV2Address = "0xd5C27770E8e2F43B959484971472a0019b17fA56";
let DODOApproveAddress = "0xeEA9F08eBfde6915AB1C0051F3eB2612DbA95d5D";
let DODOProxyV2Address = "0x97B779AD504bbd5b1BFB50e57584a876Dc65171a";
const provider = new Web3.providers.HttpProvider("https://kovan.infura.io/v3/22d4a3b2df0e47b78d458f43fe50a199");
@@ -71,6 +87,17 @@ module.exports = async (deployer, network, accounts) => {
logger.log("network type: " + network);
logger.log("Deploy time: " + new Date().toLocaleString());
if(deploySwitch.MANUAL_ADD_POOL) {
logger.log("Manual add Pool: V2");
const DPPFactoryInstance = await DPPFactory.at(DPPFactoryAddress);
var tx = await DPPFactoryInstance.addPoolByAdmin(
"0x7e83d9d94837ee82f0cc18a691da6f42f03f1d86",
"0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b",
"0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e",
"0x5e6e4B49bd79B76850650DB670Ca470ccC19d854"
);
logger.log("Manual add Pool Tx:" + tx.tx);
}
if (deploySwitch.MOCK_V2_SWAP) {
logger.log("Mock SWAP Tx: V2");
@@ -132,7 +159,8 @@ module.exports = async (deployer, network, accounts) => {
const assetTo = accounts[0];
const baseInAmount = web3.utils.toWei("1000", 'ether');
const quoteInAmount = web3.utils.toWei("100", 'mwei');
// const quoteInAmount = web3.utils.toWei("100", 'mwei');
const quoteInAmount = web3.utils.toWei("0", 'ether');
const deadline = Math.floor(new Date().getTime() / 1000 + 60 * 10);
//DVM Pool
for (var i = 0; i < POOL_PARAM.length; i++) {

View File

@@ -38,12 +38,13 @@ module.exports = {
* $ truffle test --network <network-name>
*/
deploySwitch: {
DEPLOY_V1: false,
DEPLOY_V2: false,
MOCK_TOKEN: false,
MOCK_V2_POOL: false,
MOCK_V2_SWAP: true,
HELPER_V2: false,
DEPLOY_V1: false,
DEPLOY_V2: false,
MOCK_TOKEN: false,
MOCK_V2_POOL: false,
MOCK_V2_SWAP: false,
HELPER_V2: false,
MANUAL_ADD_POOL: false
},
networks: {