diff --git a/contracts/DODOPrivatePool/impl/DPP.sol b/contracts/DODOPrivatePool/impl/DPP.sol index 53ded34..5c94b59 100644 --- a/contracts/DODOPrivatePool/impl/DPP.sol +++ b/contracts/DODOPrivatePool/impl/DPP.sol @@ -15,7 +15,6 @@ import {IERC20} from "../../intf/IERC20.sol"; import {DPPTrader} from "./DPPTrader.sol"; contract DPP is DPPTrader { - constructor() public { _FACTORY_ = msg.sender; } @@ -34,6 +33,7 @@ contract DPP is DPPTrader { ) external { require(msg.sender == _FACTORY_, 'INIT FORBIDDEN'); initOwner(owner); + _ADMIN_ = owner; _MAINTAINER_ = maintainer; _BASE_TOKEN_ = IERC20(baseTokenAddress); _QUOTE_TOKEN_ = IERC20(quoteTokenAddress); diff --git a/contracts/DODOPrivatePool/impl/DPPAdmin.sol b/contracts/DODOPrivatePool/impl/DPPAdmin.sol new file mode 100644 index 0000000..805ea83 --- /dev/null +++ b/contracts/DODOPrivatePool/impl/DPPAdmin.sol @@ -0,0 +1,58 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {IDPP} from "../intf/IDPP.sol"; +import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; + +contract DPPAdmin is InitializableOwnable { + + address public dpp; + + function init(address owner, address _dpp) external { + initOwner(owner); + dpp = _dpp; + } + + function setLpFeeRateModel(address newLpFeeRateModel) external onlyOwner { + IDPP(dpp).setLpFeeRateModel(newLpFeeRateModel); + } + + function setMtFeeRateModel(address newMtFeeRateModel) external onlyOwner { + IDPP(dpp).setMtFeeRateModel(newMtFeeRateModel); + } + + function setTradePermissionManager(address newTradePermissionManager) external onlyOwner { + IDPP(dpp).setTradePermissionManager(newTradePermissionManager); + } + + function setMaintainer(address newMaintainer) external onlyOwner { + IDPP(dpp).setMaintainer(newMaintainer); + } + + function setGasPriceSource(address newGasPriceLimitSource) external onlyOwner { + IDPP(dpp).setGasPriceSource(newGasPriceLimitSource); + } + + function setISource(address newISource) external onlyOwner { + IDPP(dpp).setISource(newISource); + } + + function setKSource(address newKSource) external onlyOwner { + IDPP(dpp).setKSource(newKSource); + } + + function setBuy(bool open) external onlyOwner { + IDPP(dpp).setBuy(open); + } + + function setSell(bool open) external onlyOwner { + IDPP(dpp).setSell(open); + } +} diff --git a/contracts/DODOPrivatePool/impl/DPPStorage.sol b/contracts/DODOPrivatePool/impl/DPPStorage.sol index 04e2c65..2b558e6 100644 --- a/contracts/DODOPrivatePool/impl/DPPStorage.sol +++ b/contracts/DODOPrivatePool/impl/DPPStorage.sol @@ -28,6 +28,7 @@ contract DPPStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; address public _FACTORY_; + address public _ADMIN_; // ============ Variables for Control ============ diff --git a/contracts/DODOPrivatePool/intf/IDPP.sol b/contracts/DODOPrivatePool/intf/IDPP.sol index 41df191..c42b5d2 100644 --- a/contracts/DODOPrivatePool/intf/IDPP.sol +++ b/contracts/DODOPrivatePool/intf/IDPP.sol @@ -21,4 +21,25 @@ interface IDPP { address gasPriceSource, address tradePermissionManager ) external; + + //=========== admin ========== + function setLpFeeRateModel(address newLpFeeRateModel) external; + + function setMtFeeRateModel(address newMtFeeRateModel) external; + + function setTradePermissionManager(address newTradePermissionManager) external; + + function setMaintainer(address newMaintainer) external; + + function setGasPriceSource(address newGasPriceLimitSource) external; + + function setISource(address newISource) external; + + function setKSource(address newKSource) external; + + function setBuy(bool open) external; + + function setSell(bool open) external; + //============================== + } diff --git a/contracts/DODOPrivatePool/intf/IDPPAdmin.sol b/contracts/DODOPrivatePool/intf/IDPPAdmin.sol new file mode 100644 index 0000000..046269a --- /dev/null +++ b/contracts/DODOPrivatePool/intf/IDPPAdmin.sol @@ -0,0 +1,13 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +interface IDPPAdmin { + function init(address owner, address _dpp) external; +} \ No newline at end of file diff --git a/contracts/DODOVendingMachine/impl/DVM.sol b/contracts/DODOVendingMachine/impl/DVM.sol index 0f24422..835cc1e 100644 --- a/contracts/DODOVendingMachine/impl/DVM.sol +++ b/contracts/DODOVendingMachine/impl/DVM.sol @@ -17,6 +17,10 @@ import {DVMFunding} from "./DVMFunding.sol"; import {DVMVault} from "./DVMVault.sol"; contract DVM is DVMTrader, DVMFunding { + constructor() public { + _FACTORY_ = msg.sender; + } + function init( address owner, address maintainer, @@ -29,7 +33,9 @@ contract DVM is DVMTrader, DVMFunding { uint256 i, uint256 k ) external { + require(msg.sender == _FACTORY_, 'INIT FORBIDDEN'); initOwner(owner); + _ADMIN_ = owner; _BASE_TOKEN_ = IERC20(baseTokenAddress); _QUOTE_TOKEN_ = IERC20(quoteTokenAddress); _LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel); diff --git a/contracts/DODOVendingMachine/impl/DVMAdmin.sol b/contracts/DODOVendingMachine/impl/DVMAdmin.sol new file mode 100644 index 0000000..66203bb --- /dev/null +++ b/contracts/DODOVendingMachine/impl/DVMAdmin.sol @@ -0,0 +1,50 @@ +/* + + 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"; + +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 setMtFeeRateModel(address newMtFeeRateModel) external onlyOwner { + IDVM(dvm).setMtFeeRateModel(newMtFeeRateModel); + } + + 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); + } +} diff --git a/contracts/DODOVendingMachine/impl/DVMStorage.sol b/contracts/DODOVendingMachine/impl/DVMStorage.sol index 0bfb276..3be6516 100644 --- a/contracts/DODOVendingMachine/impl/DVMStorage.sol +++ b/contracts/DODOVendingMachine/impl/DVMStorage.sol @@ -21,6 +21,9 @@ import {IERC20} from "../../intf/IERC20.sol"; contract DVMStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; + address public _FACTORY_; + address public _ADMIN_; + // ============ Variables for Control ============ IExternalValue public _GAS_PRICE_LIMIT_; diff --git a/contracts/DODOVendingMachine/intf/IDVM.sol b/contracts/DODOVendingMachine/intf/IDVM.sol index 1e9afd8..b8225af 100644 --- a/contracts/DODOVendingMachine/intf/IDVM.sol +++ b/contracts/DODOVendingMachine/intf/IDVM.sol @@ -33,4 +33,21 @@ interface IDVM { function sellQuote(address to) external returns (uint256); function buyShares(address to) external returns (uint256); + + + //=========== admin ========== + function setLpFeeRateModel(address newLpFeeRateModel) external; + + function setMtFeeRateModel(address newMtFeeRateModel) 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; + //============================== } diff --git a/contracts/DODOVendingMachine/intf/IDVMAdmin.sol b/contracts/DODOVendingMachine/intf/IDVMAdmin.sol new file mode 100644 index 0000000..8f24680 --- /dev/null +++ b/contracts/DODOVendingMachine/intf/IDVMAdmin.sol @@ -0,0 +1,13 @@ +/* + + 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; +} \ No newline at end of file diff --git a/contracts/Factory/DPPFactory.sol b/contracts/Factory/DPPFactory.sol index 396c785..c376696 100644 --- a/contracts/Factory/DPPFactory.sol +++ b/contracts/Factory/DPPFactory.sol @@ -13,24 +13,23 @@ import {ICloneFactory} from "../lib/CloneFactory.sol"; import {IFeeRateModel} from "../lib/FeeRateModel.sol"; import {IExternalValue} from "../lib/ExternalValue.sol"; import {IDPP} from "../DODOPrivatePool/intf/IDPP.sol"; +import {IDPPAdmin} from "../DODOPrivatePool/intf/IDPPAdmin.sol"; import {IPermissionManager} from "../lib/PermissionManager.sol"; contract DPPFactory is Ownable { address public _CLONE_FACTORY_; address public _DPP_TEMPLATE_; + address public _DPP_ADMIN_TEMPLATE_; address public _FEE_RATE_MODEL_TEMPLATE_; address public _PERMISSION_MANAGER_TEMPLATE_; address public _VALUE_SOURCE_; - //TODO: 平台修改tag的权限 + //TODO: 平台修改tag的权限 && 池子标签类型 struct DPPInfo { address creator; uint256 createTimeStamp; - //TODO:池子类型 } - //TODO:tags filter event - // base -> quote -> DPP address list mapping(address => mapping(address => address[])) _REGISTRY_; // token0 -> token1 -> DPP address list @@ -43,12 +42,14 @@ contract DPPFactory is Ownable { constructor( address cloneFactory, address dppTemplate, + address dppAdminTemplate, address defautFeeRateModelTemplate, address defaultPermissionManagerTemplate, address defaultExternalValueTemplate ) public { _CLONE_FACTORY_ = cloneFactory; _DPP_TEMPLATE_ = dppTemplate; + _DPP_ADMIN_TEMPLATE_ = dppAdminTemplate; _FEE_RATE_MODEL_TEMPLATE_ = defautFeeRateModelTemplate; _PERMISSION_MANAGER_TEMPLATE_ = defaultPermissionManagerTemplate; _VALUE_SOURCE_ = defaultExternalValueTemplate; @@ -57,25 +58,26 @@ contract DPPFactory is Ownable { function createDODOPrivatePool( address baseToken, address quoteToken, - //TODO: tag 粒度 - address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr - uint256[] memory values // feeRate,mtRate,k,i + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 i, + uint256 k ) external returns (address newPrivatePool) { - require(valueTemplates.length == 4 && values.length == 4, "Incorrect number of initialization parameters"); (address token0, address token1) = baseToken < quoteToken ? (baseToken, quoteToken) : (quoteToken, baseToken); newPrivatePool = ICloneFactory(_CLONE_FACTORY_).clone(_DPP_TEMPLATE_); IDPP(newPrivatePool).init( - msg.sender, + _createDPPAdminModel(msg.sender,newPrivatePool), msg.sender, baseToken, quoteToken, - (valueTemplates[0] == address(0) ? _createFeeRateModel(newPrivatePool, values[0]) : valueTemplates[0]), - (valueTemplates[1] == address(0) ? _createFeeRateModel(newPrivatePool, values[1]) : valueTemplates[1]), - (valueTemplates[2] == address(0) ? _createExternalValueModel(newPrivatePool, values[2]) : valueTemplates[2]), - (valueTemplates[3] == address(0) ? _createExternalValueModel(newPrivatePool, values[3]) : valueTemplates[3]), - //hardcode + _createFeeRateModel(newPrivatePool, lpFeeRate), + _createFeeRateModel(newPrivatePool, mtFeeRate), + _createExternalValueModel(newPrivatePool, k), + _createExternalValueModel(newPrivatePool, i), + //TODO:hardcode _createExternalValueModel(msg.sender, 10**22), + //TODO:讨论 _createPermissionManager(msg.sender) ); @@ -88,24 +90,30 @@ contract DPPFactory is Ownable { createTimeStamp: block.timestamp }) ); - return newPrivatePool; } function _createFeeRateModel(address owner, uint256 feeRate) internal returns (address feeRateModel){ feeRateModel = ICloneFactory(_CLONE_FACTORY_).clone(_FEE_RATE_MODEL_TEMPLATE_); IFeeRateModel(feeRateModel).init(owner, feeRate); - return feeRateModel; } function _createPermissionManager(address owner) internal returns (address permissionManager) { permissionManager = ICloneFactory(_CLONE_FACTORY_).clone(_PERMISSION_MANAGER_TEMPLATE_); IPermissionManager(permissionManager).initOwner(owner); - return permissionManager; } function _createExternalValueModel(address owner, uint256 value) internal returns (address valueModel) { valueModel = ICloneFactory(_CLONE_FACTORY_).clone(_VALUE_SOURCE_); IExternalValue(valueModel).init(owner, value); - return valueModel; + } + + function _createDPPAdminModel(address owner, address dpp) internal returns (address adminModel) { + adminModel = ICloneFactory(_CLONE_FACTORY_).clone(_DPP_ADMIN_TEMPLATE_); + IDPPAdmin(adminModel).init(owner,dpp); + } + + //TODO: 讨论 or 升级整个Factory + function updateAdminTemplate(address _newDPPAdminTemplate) external onlyOwner { + _DPP_ADMIN_TEMPLATE_ = _newDPPAdminTemplate; } } diff --git a/contracts/Factory/DVMFactory.sol b/contracts/Factory/DVMFactory.sol index 4153f85..24fa89a 100644 --- a/contracts/Factory/DVMFactory.sol +++ b/contracts/Factory/DVMFactory.sol @@ -12,19 +12,21 @@ import {Ownable} from "../lib/Ownable.sol"; import {ICloneFactory} from "../lib/CloneFactory.sol"; import {IConstFeeRateModel} from "../lib/ConstFeeRateModel.sol"; import {IDVM} from "../DODOVendingMachine/intf/IDVM.sol"; +import {IDVMAdmin} from "../DODOVendingMachine/intf/IDVMAdmin.sol"; import {IPermissionManager} from "../lib/PermissionManager.sol"; contract DVMFactory is Ownable { address public _CLONE_FACTORY_; address public _DVM_TEMPLATE_; + address public _DVM_ADMIN_TEMPLATE_; address public _FEE_RATE_MODEL_TEMPLATE_; address public _PERMISSION_MANAGER_TEMPLATE_; address public _DEFAULT_GAS_PRICE_SOURCE_; + //TODO: 平台修改tag的权限 && 池子标签类型 struct DVMInfo { address creator; uint256 createTimeStamp; - //TODO:other tags } // base -> quote -> DVM address list @@ -39,12 +41,14 @@ contract DVMFactory is Ownable { constructor( address cloneFactory, address dvmTemplate, + address dvmAdminTemplate, address feeRateModelTemplate, address permissionManagerTemplate, address defaultGasPriceSource ) public { _CLONE_FACTORY_ = cloneFactory; _DVM_TEMPLATE_ = dvmTemplate; + _DVM_ADMIN_TEMPLATE_ = dvmAdminTemplate; _FEE_RATE_MODEL_TEMPLATE_ = feeRateModelTemplate; _PERMISSION_MANAGER_TEMPLATE_ = permissionManagerTemplate; _DEFAULT_GAS_PRICE_SOURCE_ = defaultGasPriceSource; @@ -62,13 +66,12 @@ contract DVMFactory is Ownable { newVendingMachine = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_); IDVM(newVendingMachine).init( - msg.sender, + _createDVMAdminModel(msg.sender,newVendingMachine), msg.sender, baseToken, quoteToken, - //TODO:标准库 统一的feeRateModel,owner归平台控制 - _createConstFeeRateModel(newVendingMachine, lpFeeRate), - _createConstFeeRateModel(newVendingMachine, mtFeeRate), + _createFeeRateModel(newVendingMachine, lpFeeRate), + _createFeeRateModel(newVendingMachine, mtFeeRate), _createPermissionManager(msg.sender), _DEFAULT_GAS_PRICE_SOURCE_, i, @@ -87,16 +90,24 @@ contract DVMFactory is Ownable { return newVendingMachine; } - function _createConstFeeRateModel(address owner, uint256 feeRate) internal returns (address feeRateModel) { + function _createFeeRateModel(address owner, uint256 feeRate) internal returns (address feeRateModel) { feeRateModel = ICloneFactory(_CLONE_FACTORY_).clone(_FEE_RATE_MODEL_TEMPLATE_); IConstFeeRateModel(feeRateModel).init(owner, feeRate); - return feeRateModel; } function _createPermissionManager(address owner) internal returns (address permissionManager) { permissionManager = ICloneFactory(_CLONE_FACTORY_).clone(_PERMISSION_MANAGER_TEMPLATE_); IPermissionManager(permissionManager).initOwner(owner); - return permissionManager; + } + + function _createDVMAdminModel(address owner, address dvm) internal returns (address adminModel) { + adminModel = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_ADMIN_TEMPLATE_); + IDVMAdmin(adminModel).init(owner,dvm); + } + + //TODO: 讨论 or 升级整个Factory + function updateAdminTemplate(address _newDVMAdminTemplate) external onlyOwner { + _DVM_ADMIN_TEMPLATE_ = _newDVMAdminTemplate; } function getVendingMachine(address baseToken, address quoteToken) diff --git a/contracts/SmartRoute/DODOV2Proxy01.sol b/contracts/SmartRoute/DODOV2Proxy01.sol index dbb36d4..ddd0f4e 100644 --- a/contracts/SmartRoute/DODOV2Proxy01.sol +++ b/contracts/SmartRoute/DODOV2Proxy01.sol @@ -130,7 +130,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { require(baseActualInAmount >= baseMinAmount && quoteActualInAmount >= quoteMinAmount, "DODOV2Proxy01: deposit amount is not enough"); } - //TODO:ETH + //TODO:ETH 构造data function removeDVMLiquidity( address DVMAddress, address to, @@ -140,8 +140,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { uint256 deadline ) external virtual override payable judgeExpired(deadline) returns (uint256 baseOutAmount,uint256 quoteOutAmount) { require(shares > 0, "DODOV2Proxy01: Insufficient_Liquidity"); - IDODOV2(smartApprove).claimTokens(DVMAddress, msg.sender, DVMAddress, shares); - (baseOutAmount,quoteOutAmount) = IDODOV2(DVMAddress).sellShares(to); + (baseOutAmount,quoteOutAmount) = IDODOV2(DVMAddress).sellShares(to, shares, ""); require(baseOutAmount >= baseOutMinAmount && quoteOutAmount >= quoteOutMinAmount,"DODOV2Proxy01: withdraw amount is not enough"); } @@ -151,11 +150,13 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { address quoteToken, uint256 baseInAmount, uint256 quoteInAmount, - address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr - uint256[] memory values, // feeRate,mtRate,k,i + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 i, + uint256 k, uint256 deadline ) external virtual override payable judgeExpired(deadline) returns (address newPrivatePool) { - newPrivatePool = IDODOV2(dppFactory).createDODOPrivatePool(baseToken,quoteToken,valueTemplates,values); + newPrivatePool = IDODOV2(dppFactory).createDODOPrivatePool(baseToken, quoteToken, lpFeeRate, mtFeeRate, i, k); if(baseInAmount > 0) IDODOV2(smartApprove).claimTokens(baseToken, msg.sender, newPrivatePool, baseInAmount); if(quoteInAmount > 0) diff --git a/contracts/SmartRoute/SmartSwap.sol b/contracts/SmartRoute/SmartSwap.sol index 94a0601..9f00242 100644 --- a/contracts/SmartRoute/SmartSwap.sol +++ b/contracts/SmartRoute/SmartSwap.sol @@ -40,8 +40,6 @@ contract SmartSwap is Ownable { uint256 timeStamp ); - event ExternalRecord(address indexed to, address indexed sender); - constructor( address _smartApprove, address _dodoSellHelper, @@ -76,9 +74,8 @@ contract SmartSwap is Ownable { } for (uint256 i = 0; i < dodoPairs.length; i++) { - uint256 curDirection = directions[i]; address curDodoPair = dodoPairs[i]; - if (curDirection == 0) { + if (directions[i] == 0) { address curDodoBase = IDODO(curDodoPair)._BASE_TOKEN_(); uint256 curAmountIn = IERC20(curDodoBase).balanceOf(address(this)); IERC20(curDodoBase).universalApprove(curDodoPair, curAmountIn); @@ -139,6 +136,5 @@ contract SmartSwap is Ownable { require(returnAmount >= minReturnAmount, "DODO SmartSwap: Return amount is not enough"); IERC20(toToken).universalTransfer(msg.sender, returnAmount); emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount, block.timestamp); - emit ExternalRecord(to, msg.sender); } } diff --git a/contracts/intf/IDODOV2.sol b/contracts/intf/IDODOV2.sol index c9c3e91..c2f7ee3 100644 --- a/contracts/intf/IDODOV2.sol +++ b/contracts/intf/IDODOV2.sol @@ -11,13 +11,21 @@ pragma experimental ABIEncoderV2; import {IERC20} from "./IERC20.sol"; interface IDODOV2 { - function createDODOPrivatePool( - address baseToken, - address quoteToken, - address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr - uint256[] memory values //feeRate,mtRate,k,i - ) external returns (address newPrivatePool); + //========== Common ================== + + function sellBase(address to) external returns (uint256 receiveQuoteAmount); + + function sellQuote(address to) external returns (uint256 receiveBaseAmount); + + function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve); + + function _BASE_TOKEN_() external returns (address); + + function _QUOTE_TOKEN_() external returns (address); + + //========== DODOVendingMachine ======== + function createDODOVendingMachine( address baseToken, address quoteToken, @@ -27,24 +35,23 @@ interface IDODOV2 { uint256 k ) external returns (address newVendingMachine); - function sellBase(address to) external returns (uint256 receiveQuoteAmount); - - function sellQuote(address to) external returns (uint256 receiveBaseAmount); - function buyShares(address to) external returns (uint256,uint256,uint256); - function sellShares(address to) external returns (uint256,uint256); - - - function getVaultReserve() external view returns (uint256 baseReserve, uint256 quoteReserve); - - function _BASE_TOKEN_() external returns (address); - - function _QUOTE_TOKEN_() external returns (address); + function sellShares(address to, uint256 amount, bytes calldata data) external returns (uint256,uint256); //========== DODOPrivatePool =========== + function initTargetAndReserve() external; + function createDODOPrivatePool( + address baseToken, + address quoteToken, + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 i, + uint256 k + ) external returns (address newPrivatePool); + function reset( uint256 newLpFeeRate, uint256 newMtFeeRate, diff --git a/contracts/intf/IDODOV2Proxy01.sol b/contracts/intf/IDODOV2Proxy01.sol index 7fad30d..e740431 100644 --- a/contracts/intf/IDODOV2Proxy01.sol +++ b/contracts/intf/IDODOV2Proxy01.sol @@ -74,8 +74,10 @@ interface IDODOV2Proxy01 { address quoteToken, uint256 baseInAmount, uint256 quoteInAmount, - address[] memory valueTemplates, //feeRateAddr,mtRateAddr,kAddr,iAddr - uint256[] memory values, // feeRate,mtRate,k,i + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 i, + uint256 k, uint256 deadline ) external payable returns (address newPrivatePool); diff --git a/deploy-detail.txt b/deploy-detail.txt index 3946e74..e69de29 100644 --- a/deploy-detail.txt +++ b/deploy-detail.txt @@ -1,8 +0,0 @@ -==================================================== -network type: kovan -Deploy time: 2020/11/20 上午10:58:49 -Deploy type: Smart Route -SmartApprove Address: 0x0E5cf0e4658E371f93a6bDB7E72d6789Aff08666 -DODOSellHelper Address: 0xbdEae617F2616b45DCB69B287D52940a76035Fe3 -SmartSwap Address: 0x767A6FB2f5e908c4E573CaA2bc7f53D468ffd78E -SmartApprovce setSmartSwap tx: 0xc9efe8b60cba3a2d288d487a7e512a3cfcdd017a25a923477323067546fbbec2 diff --git a/test/Proxy/proxy.test.ts b/test/Proxy/proxy.test.ts new file mode 100644 index 0000000..45daa09 --- /dev/null +++ b/test/Proxy/proxy.test.ts @@ -0,0 +1,155 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +// import * as assert from 'assert'; + +import { decimalStr, mweiStr} from '../utils/Converter'; +import { logGas } from '../utils/Log'; +import { ProxyContext, getProxyContext } from '../utils/ProxyContext'; +import { assert } from 'chai'; + +let lp: string; +let project: string; +let trader: string; + +let config = { + lpFeeRate: decimalStr("0.002"), + mtFeeRate: decimalStr("0.001"), + k: decimalStr("0.1"), + i: decimalStr("100"), +}; + +async function init(ctx: ProxyContext): Promise { + lp = ctx.SpareAccounts[0]; + project = ctx.SpareAccounts[1]; + trader = ctx.SpareAccounts[2]; + await ctx.approveProxy(lp); + await ctx.approveProxy(project); + await ctx.approveProxy(trader); + + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("100000")); + await ctx.mintTestToken(project, ctx.DODO, decimalStr("100000")); + await ctx.mintTestToken(trader, ctx.DODO, decimalStr("100000")); + + await ctx.mintTestToken(lp, ctx.USDT, mweiStr("100000")); + await ctx.mintTestToken(project, ctx.USDT, mweiStr("100000")); + + await ctx.mintTestToken(lp, ctx.WETH, decimalStr("70")); + await ctx.mintTestToken(project, ctx.WETH, decimalStr("70")); +} + +async function initCreateDVM(ctx: ProxyContext, token0: any, token1:any, token0Amount: string, token1Amount: string): Promise { + let PROXY = ctx.DODOProxy; + let dvmAddress; + let shares; + (dvmAddress, shares) = await PROXY.methods.createDODOVendingMachine( + token0.options.address, + token1.options.address, + token0Amount, + token1Amount, + config.lpFeeRate, + config.mtFeeRate, + config.i, + config.k, + Math.floor(new Date().getTime()/1000 + 60 * 10); + ).send(ctx.sendParam(project)); + console.log("create dvmAddress: ", dvmAddress); + console.log("create shares: ", shares); +} + +async function initCreateDPP(ctx: ProxyContext, token0: any, token1:any, token0Amount: string, token1Amount: string): Promise { + let PROXY = ctx.DODOProxy; + let dppAddress = await PROXY.methods.createDODOPrivatePool( + token0.options.address, + token1.options.address, + token0Amount, + token1Amount, + config.lpFeeRate, + config.mtFeeRate, + config.i, + config.k, + Math.floor(new Date().getTime()/1000 + 60 * 10); + ).send(ctx.sendParam(project)); + console.log("create dppAddress: ", dppAddress); + console.log("create shares: ", shares); +} + +describe("DODOProxyV2.0", () => { + let snapshotId: string; + let ctx: ProxyContext; + + before(async () => { + ctx = await getProxyContext(); + await init(ctx); + await initCreateDVM(ctx,ctx.DODO,ctx.USDT,decimalStr("10000"),decimalStr("10000")); + await initCreateDVM(ctx,ctx.WETH,ctx.USDT,decimalStr("50"),decimalStr("10000")); + await initCreateDPP(ctx,ctx.DODO,ctx.USDT,decimalStr("10000"),decimalStr("10000")); + await initCreateDPP(ctx,ctx.WETH,ctx.USDT,decimalStr("50"),decimalStr("10000")); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("DODOProxy", () => { + /** + * 1. 创建空池子 + * 2. 创建ERC20 Token DVM + * 3. 创建ETH && ERC20 Token + */ + it("createDVM", async () => { + + }); + + /** + * 1. 添加ERC20 Amount + * 2. 添加ERC20 + ETH + */ + it("addLiquidityToDVM", async () => { + + }); + + + /** + * 1. 移除ERC20 Amount + * 2. 移除ERC20 + ETH + */ + it("removeLiquidityToDVM", async () => { + + }); + + /** + * 1. 创建空池子 + * 2. 创建ERC20 DPP + * 3. 创建ETH && ERC20 Token + */ + it("createDPP", async () => { + + }); + + + /** + * + */ + it("resetDPP", async () => { + + }); + + + /** + * + */ + it("dodoSwap", async () => { + + }); + + }); +}); diff --git a/test/utils/Contracts.ts b/test/utils/Contracts.ts index 4f4efa6..1236a82 100644 --- a/test/utils/Contracts.ts +++ b/test/utils/Contracts.ts @@ -35,6 +35,14 @@ export const DVM_PROXY_NAME = "DVMProxy" export const CONST_FEE_RATE_MODEL_NAME = "ConstFeeRateModel" export const PERMISSION_MANAGER_NAME = "PermissionManager" export const EXTERNAL_VALUE_NAME = "ExternalValue" +export const DODO_PROXY_NAME = "DODOV2Proxy01" +export const FEE_RATE_MODEL_NAME = "FeeRateModel" +export const DPP_NAME = "DPP" +export const DPP_FACTORY_NAME = "DPPFactory" +export const SMART_APPROVE = "SmartApprove" +export const DODO_SELL_HELPER = "DODOSellHelper" +export const DVM_ADMIN_NAME = "DVMAdmin" +export const DPP_ADMIN_NAME = "DPPAdmin" interface ContractJson { abi: any; diff --git a/test/utils/Converter.ts b/test/utils/Converter.ts index ba7269d..53edd17 100644 --- a/test/utils/Converter.ts +++ b/test/utils/Converter.ts @@ -8,4 +8,8 @@ export function decimalStr(value: string): string { export function gweiStr(gwei: string): string { return new BigNumber(gwei).multipliedBy(10 ** 9).toFixed(0, BigNumber.ROUND_DOWN) -} \ No newline at end of file +} + +export function mweiStr(gwei: string): string { + return new BigNumber(gwei).multipliedBy(10 ** 6).toFixed(0, BigNumber.ROUND_DOWN) +}s \ No newline at end of file diff --git a/test/utils/ProxyContext.ts b/test/utils/ProxyContext.ts new file mode 100644 index 0000000..945ca5d --- /dev/null +++ b/test/utils/ProxyContext.ts @@ -0,0 +1,151 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +import BigNumber from 'bignumber.js'; +import Web3 from 'web3'; +import { Contract } from 'web3-eth-contract'; + +import * as contracts from './Contracts'; +import { decimalStr, MAX_UINT256 } from './Converter'; +import { EVM, getDefaultWeb3 } from './EVM'; +import * as log from './Log'; + +BigNumber.config({ + EXPONENTIAL_AT: 1000, + DECIMAL_PLACES: 80, +}); + + +export class ProxyContext { + EVM: EVM; + Web3: Web3; + DODOProxy: Contract; + DVMFactory: Contract; + DPPFactory: Contract; + SmartApprove: Contract; + + //token + DODO: Contract; + USDT: Contract; + WETH: Contract; + + Deployer: string; + Maintainer: string; + SpareAccounts: string[]; + + constructor() { } + + async init() { + this.EVM = new EVM(); + this.Web3 = getDefaultWeb3(); + + var WETH = await contracts.newContract( + contracts.WETH_CONTRACT_NAME + ); + + var cloneFactory = await contracts.newContract( + contracts.CLONE_FACTORY_CONTRACT_NAME + ); + var dvmTemplate = await contracts.newContract(contracts.DVM_NAME) + var dppTemplate = await contracts.newContract(contracts.DPP_NAME) + var dvmAdminTemplate = await contracts.newContract(contracts.DVM_ADMIN_NAME) + var dppAdminTemplate = await contracts.newContract(contracts.DPP_ADMIN_NAME) + var feeRateModelTemplate = await contracts.newContract(contracts.FEE_RATE_MODEL_NAME) + var permissionManagerTemplate = await contracts.newContract(contracts.PERMISSION_MANAGER_NAME) + var vauleSource = await contracts.newContract(contracts.EXTERNAL_VALUE_NAME) + + this.DVMFactory = await contracts.newContract(contracts.DVM_FACTORY_NAME, + [ + cloneFactory.options.address, + dvmTemplate.options.address, + dvmAdminTemplate.options.address, + feeRateModelTemplate.options.address, + permissionManagerTemplate.options.address, + vauleSource.options.address + ] + ) + + this.DPPFactory = await contracts.newContract(contracts.DPP_FACTORY_NAME, + [ + cloneFactory.options.address, + dppTemplate.options.address, + dppAdminTemplate.options.address, + feeRateModelTemplate.options.address, + permissionManagerTemplate.options.address, + vauleSource.options.address + ] + ) + + this.SmartApprove = await contracts.newContract( + contracts.SMART_APPROVE + ); + + var dodoSellHelper = await contracts.newContract( + contracts.DODO_SELL_HELPER + ); + + this.DODOProxy = await contracts.newContract(contracts.DODO_PROXY_NAME, + [ + dvmFactory.options.address, + dppFactory.options.address, + WETH.options.address, + smartApprove.options.address, + dodoSellHelper.options.address + ] + ); + + this.DODO = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["DODO Token", "DODO", 18] + ); + this.USDT = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["USDT Token", "USDT", 6] + ); + this.WETH = await contracts.newContract( + contracts.WETH_CONTRACT_NAME + ); + + const allAccounts = await this.Web3.eth.getAccounts(); + this.Deployer = allAccounts[0]; + this.Maintainer = allAccounts[1]; + this.SpareAccounts = allAccounts.slice(2, 10); + + console.log(log.blueText("[Init DVM context]")); + } + + sendParam(sender, value = "0") { + return { + from: sender, + gas: process.env["COVERAGE"] ? 10000000000 : 7000000, + gasPrice: process.env.GAS_PRICE, + value: decimalStr(value), + }; + } + + async mintTestToken(to: string, token: Contract, amount: string) { + await token.methods.mint(to, amount).send(this.sendParam(this.Deployer)); + } + + async approveProxy(account: string) { + await this.DODO.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + await this.USDT.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + await this.WETH.methods + .approve(this.SmartApprove.options.address, MAX_UINT256) + .send(this.sendParam(account)); + } +} + +export async function getProxyContext(): Promise { + var context = new ProxyContext(); + await context.init(); + return context; +}