From f5ceb29843cd91cd1323268b2bdf56ca1b23c29a Mon Sep 17 00:00:00 2001 From: owen05 Date: Mon, 14 Dec 2020 01:22:30 +0800 Subject: [PATCH] add crowdpooling factory and proxy --- contracts/CrowdPooling/intf/ICP.sol | 36 +++++ contracts/DODOPrivatePool/impl/DPPTrader.sol | 6 +- .../DODOVendingMachine/impl/DVMTrader.sol | 6 +- contracts/Factory/CrowdPoolingFactory.sol | 126 ++++++++++++++++++ contracts/SmartRoute/DODOV2Proxy01.sol | 48 +++++++ contracts/SmartRoute/intf/IDODOV2.sol | 15 +++ contracts/SmartRoute/intf/IDODOV2Proxy01.sol | 17 +++ 7 files changed, 248 insertions(+), 6 deletions(-) create mode 100644 contracts/CrowdPooling/intf/ICP.sol create mode 100644 contracts/Factory/CrowdPoolingFactory.sol diff --git a/contracts/CrowdPooling/intf/ICP.sol b/contracts/CrowdPooling/intf/ICP.sol new file mode 100644 index 0000000..b1193ba --- /dev/null +++ b/contracts/CrowdPooling/intf/ICP.sol @@ -0,0 +1,36 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +interface ICP { + function init( + address[] calldata addressList, + uint256[] calldata timeLine, + uint256[] calldata valueList + ) external; + + //============================== + + + //============================== + + function bid(address to) external; + + function cancel(address assetTo, uint256 amount) external; + + function settle() external; + + function emergencySettle() external; + + function claimBase() external; + + function claimQuote() external; + + function claimLPToken() external; +} diff --git a/contracts/DODOPrivatePool/impl/DPPTrader.sol b/contracts/DODOPrivatePool/impl/DPPTrader.sol index 1cfe139..deab4e5 100644 --- a/contracts/DODOPrivatePool/impl/DPPTrader.sol +++ b/contracts/DODOPrivatePool/impl/DPPTrader.sol @@ -20,11 +20,11 @@ contract DPPTrader is DPPVault { // ============ Events ============ event DODOSwap( - address indexed fromToken, - address indexed toToken, + address fromToken, + address toToken, uint256 fromAmount, uint256 toAmount, - address indexed trader + address trader ); // ============ Modifiers ============ diff --git a/contracts/DODOVendingMachine/impl/DVMTrader.sol b/contracts/DODOVendingMachine/impl/DVMTrader.sol index 8322416..e5f6e2d 100644 --- a/contracts/DODOVendingMachine/impl/DVMTrader.sol +++ b/contracts/DODOVendingMachine/impl/DVMTrader.sol @@ -21,11 +21,11 @@ contract DVMTrader is DVMVault { // ============ Events ============ event DODOSwap( - address indexed fromToken, - address indexed toToken, + address fromToken, + address toToken, uint256 fromAmount, uint256 toAmount, - address indexed trader + address trader ); // ============ Modifiers ============ diff --git a/contracts/Factory/CrowdPoolingFactory.sol b/contracts/Factory/CrowdPoolingFactory.sol new file mode 100644 index 0000000..c043994 --- /dev/null +++ b/contracts/Factory/CrowdPoolingFactory.sol @@ -0,0 +1,126 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {Ownable} from "../lib/Ownable.sol"; +import {ICloneFactory} from "../lib/CloneFactory.sol"; +import {ICP} from "../CrowdPooling/intf/ICP.sol"; + +contract CrowdPoolingFactory { + // ============ Templates ============ + + address public immutable _CLONE_FACTORY_; + address public immutable _CP_TEMPLATE_; + address public immutable _UNOWNED_DVM_FACTORY_; + address public immutable _FEE_RATE_MODEL_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_; + + // ============ Registry ============ + + // base -> quote -> CP address list + mapping(address => mapping(address => address[])) public _REGISTRY_; + // creator -> CP address list + mapping(address => address[]) public _USER_REGISTRY_; + + // ============ Events ============ + + event NewCP( + address indexed baseToken, + address indexed quoteToken, + address indexed creator, + address cp + ); + + // ============ Functions ============ + + constructor( + address cloneFactory, + address cpTemplate, + address unOwnedDvmFactory, + address feeRateModelTemplate, + address defaultMaintainer, + address defaultMtFeeRateModel, + address defaultPermissionManager, + address defaultGasPriceSource + ) public { + _CLONE_FACTORY_ = cloneFactory; + _CP_TEMPLATE_ = cpTemplate; + _UNOWNED_DVM_FACTORY_ = unOwnedDvmFactory; + _FEE_RATE_MODEL_TEMPLATE_ = feeRateModelTemplate; + _DEFAULT_MAINTAINER_ = defaultMaintainer; + _DEFAULT_MT_FEE_RATE_MODEL_ = defaultMtFeeRateModel; + _DEFAULT_PERMISSION_MANAGER_ = defaultPermissionManager; + _DEFAULT_GAS_PRICE_SOURCE_ = defaultGasPriceSource; + } + + function createCrowdPooling() external returns (address newCrowdPooling) { + newCrowdPooling = ICloneFactory(_CLONE_FACTORY_).clone(_CP_TEMPLATE_); + } + + function initCrowdPooling( + address cpAddress, + address creator, + address baseToken, + address quoteToken, + uint256[] memory timeLine, + uint256[] memory valueList + ) external { + { + address[] memory addressList = new address[](7); + addressList[0] = creator; + addressList[1] = _DEFAULT_MAINTAINER_; + addressList[2] = baseToken; + addressList[3] = quoteToken; + addressList[4] = _DEFAULT_PERMISSION_MANAGER_; + addressList[5] = _DEFAULT_MT_FEE_RATE_MODEL_; + addressList[6] = _UNOWNED_DVM_FACTORY_; + + ICP(cpAddress).init( + addressList, + timeLine, + valueList + ); + } + + _REGISTRY_[baseToken][quoteToken].push(cpAddress); + _USER_REGISTRY_[creator].push(cpAddress); + + emit NewCP(baseToken, quoteToken, creator, cpAddress); + } + + // ============ View Functions ============ + + function getCrowdPooling(address baseToken, address quoteToken) + external + view + returns (address[] memory pools) + { + return _REGISTRY_[baseToken][quoteToken]; + } + + function getCrowdPoolingBidirection(address token0, address token1) + external + view + returns (address[] memory baseToken0Pools, address[] memory baseToken1Pools) + { + return (_REGISTRY_[token0][token1], _REGISTRY_[token1][token0]); + } + + function getCrowdPoolingByUser(address user) + external + view + returns (address[] memory pools) + { + return _USER_REGISTRY_[user]; + } +} diff --git a/contracts/SmartRoute/DODOV2Proxy01.sol b/contracts/SmartRoute/DODOV2Proxy01.sol index de845a9..f6a0468 100644 --- a/contracts/SmartRoute/DODOV2Proxy01.sol +++ b/contracts/SmartRoute/DODOV2Proxy01.sol @@ -33,6 +33,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, Ownable { address public immutable _DODO_SELL_HELPER_; address public immutable _DVM_FACTORY_; address public immutable _DPP_FACTORY_; + address public immutable _CP_FACTORY_; mapping (address => bool) public isWhiteListed; // ============ Events ============ @@ -59,12 +60,14 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, Ownable { constructor( address dvmFactory, address dppFactory, + address cpFactory, address payable weth, address dodoApprove, address dodoSellHelper ) public { _DVM_FACTORY_ = dvmFactory; _DPP_FACTORY_ = dppFactory; + _CP_FACTORY_ = cpFactory; _WETH_ = weth; _DODO_APPROVE_ = dodoApprove; _DODO_SELL_HELPER_ = dodoSellHelper; @@ -551,6 +554,51 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, Ownable { return 0; } + //============ CrowdPooling Functions (create & bid) ============ + + function createCrowdPooling( + address baseToken, + address quoteToken, + uint256 baseInAmount, + uint256[] memory timeLine, + uint256[] memory valueList, + uint256 deadLine + ) external override judgeExpired(deadLine) returns (address newCrowdPooling) { + address _baseToken = baseToken; + address _quoteToken = quoteToken == _ETH_ADDRESS_ ? _WETH_ : quoteToken; + + newCrowdPooling = IDODOV2(_CP_FACTORY_).createCrowdPooling(); + + _deposit( + msg.sender, + newCrowdPooling, + _baseToken, + baseInAmount, + false + ); + + + IDODOV2(_CP_FACTORY_).initCrowdPooling( + newCrowdPooling, + msg.sender, + _baseToken, + _quoteToken, + timeLine, + valueList + ); + } + + function bid( + address assetTo, + address cpAddress, + uint256 quoteAmount, + uint8 flag, // 0 - ERC20, 1 - quoteInETH + uint256 deadLine + ) external override payable judgeExpired(deadLine) { + _deposit(msg.sender, cpAddress, IDODOV2(cpAddress)._QUOTE_TOKEN_(), quoteAmount, flag == 1); + IDODOV2(cpAddress).bid(assetTo); + } + function addLiquidityToV1( address to, diff --git a/contracts/SmartRoute/intf/IDODOV2.sol b/contracts/SmartRoute/intf/IDODOV2.sol index 5a5c9ca..9db1a69 100644 --- a/contracts/SmartRoute/intf/IDODOV2.sol +++ b/contracts/SmartRoute/intf/IDODOV2.sol @@ -63,4 +63,19 @@ interface IDODOV2 { uint256 baseOutAmount, uint256 quoteOutAmount ) external; + + //========== CrowdPooling =========== + + function createCrowdPooling() external returns (address newCrowdPooling); + + function initCrowdPooling( + address cpAddress, + address creator, + address baseToken, + address quoteToken, + uint256[] memory timeLine, + uint256[] memory valueList + ) external; + + function bid(address to) external; } \ No newline at end of file diff --git a/contracts/SmartRoute/intf/IDODOV2Proxy01.sol b/contracts/SmartRoute/intf/IDODOV2Proxy01.sol index afb5f54..c64840c 100644 --- a/contracts/SmartRoute/intf/IDODOV2Proxy01.sol +++ b/contracts/SmartRoute/intf/IDODOV2Proxy01.sol @@ -98,6 +98,23 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 { uint256 deadLine ) external payable; + function createCrowdPooling( + address baseToken, + address quoteToken, + uint256 baseInAmount, + uint256[] memory timeLine, + uint256[] memory valueList, + uint256 deadLine + ) external returns (address newCrowdPooling); + + function bid( + address assetTo, + address cpAddress, + uint256 quoteAmount, + uint8 flag, // 0 - ERC20, 1 - quoteInETH + uint256 deadLine + ) external payable; + function addLiquidityToV1( address to, address pair,