From 8da583d5a88d90648ea58570dd309d5ef1224375 Mon Sep 17 00:00:00 2001 From: owen05 Date: Wed, 25 Nov 2020 17:08:28 +0800 Subject: [PATCH] fix admin control && update proxy test framework --- contracts/DODOPrivatePool/impl/DPP.sol | 10 +- contracts/DODOPrivatePool/impl/DPPAdmin.sol | 13 ++ contracts/DODOPrivatePool/impl/DPPStorage.sol | 7 +- contracts/DODOPrivatePool/impl/DPPVault.sol | 17 +- contracts/DODOPrivatePool/intf/IDPP.sol | 6 + contracts/DODOVendingMachine/impl/DVM.sol | 5 - .../DODOVendingMachine/impl/DVMAdmin.sol | 5 + .../DODOVendingMachine/impl/DVMStorage.sol | 3 - contracts/Factory/DPPFactory.sol | 82 +++++---- contracts/Factory/DVMFactory.sol | 30 ++-- contracts/SmartRoute/DODOV2Proxy01.sol | 19 ++- .../{SmartSwap.sol => SmartSwap01.sol} | 52 +++--- contracts/intf/IDODOV2.sol | 13 +- contracts/lib/UniversalERC20.sol | 2 +- migrations/1_initial_migration.js | 2 +- migrations/2_deploy.js | 8 +- route-test.sh | 2 - test/Proxy/proxy.dpp.test.ts | 161 ++++++++++++++++++ .../{proxy.test.ts => proxy.dvm.test.ts} | 56 ++---- test/Route/Route.test.ts | 8 +- test/utils/Contracts.ts | 2 +- test/utils/Converter.ts | 2 +- test/utils/ProxyContext.ts | 34 ++-- truffle-config.js | 2 +- truffle-test.sh | 19 +++ 25 files changed, 383 insertions(+), 177 deletions(-) rename contracts/SmartRoute/{SmartSwap.sol => SmartSwap01.sol} (73%) delete mode 100644 route-test.sh create mode 100644 test/Proxy/proxy.dpp.test.ts rename test/Proxy/{proxy.test.ts => proxy.dvm.test.ts} (62%) create mode 100644 truffle-test.sh diff --git a/contracts/DODOPrivatePool/impl/DPP.sol b/contracts/DODOPrivatePool/impl/DPP.sol index 5c94b59..5d12d87 100644 --- a/contracts/DODOPrivatePool/impl/DPP.sol +++ b/contracts/DODOPrivatePool/impl/DPP.sol @@ -15,13 +15,10 @@ import {IERC20} from "../../intf/IERC20.sol"; import {DPPTrader} from "./DPPTrader.sol"; contract DPP is DPPTrader { - constructor() public { - _FACTORY_ = msg.sender; - } - function init( address owner, address maintainer, + address operator, address baseTokenAddress, address quoteTokenAddress, address lpFeeRateModel, @@ -29,12 +26,13 @@ contract DPP is DPPTrader { address kSource, address iSource, address gasPriceSource, + address dodoSmartApprove, address tradePermissionManager ) external { - require(msg.sender == _FACTORY_, 'INIT FORBIDDEN'); initOwner(owner); _ADMIN_ = owner; _MAINTAINER_ = maintainer; + _OPERATOR_ = operator; _BASE_TOKEN_ = IERC20(baseTokenAddress); _QUOTE_TOKEN_ = IERC20(quoteTokenAddress); _LP_FEE_RATE_MODEL_ = IFeeRateModel(lpFeeRateModel); @@ -43,6 +41,8 @@ contract DPP is DPPTrader { _K_ = IExternalValue(kSource); _GAS_PRICE_LIMIT_ = IExternalValue(gasPriceSource); _TRADE_PERMISSION_ = IPermissionManager(tradePermissionManager); + _DODO_SMART_APPROVE_ = dodoSmartApprove; + _resetTargetAndReserve(); } // ============ Version Control ============ diff --git a/contracts/DODOPrivatePool/impl/DPPAdmin.sol b/contracts/DODOPrivatePool/impl/DPPAdmin.sol index 805ea83..af11805 100644 --- a/contracts/DODOPrivatePool/impl/DPPAdmin.sol +++ b/contracts/DODOPrivatePool/impl/DPPAdmin.sol @@ -36,6 +36,10 @@ contract DPPAdmin is InitializableOwnable { IDPP(dpp).setMaintainer(newMaintainer); } + function setOperator(address newOperator) external onlyOwner { + IDPP(dpp).setOperator(newOperator); + } + function setGasPriceSource(address newGasPriceLimitSource) external onlyOwner { IDPP(dpp).setGasPriceSource(newGasPriceLimitSource); } @@ -55,4 +59,13 @@ contract DPPAdmin is InitializableOwnable { function setSell(bool open) external onlyOwner { IDPP(dpp).setSell(open); } + + function retrieve(address payable to,address token,uint256 amount) external onlyOwner { + IDPP(dpp).retrieve(to,token,amount); + } + + // ============ Admin Version Control ============ + function version() external pure returns (uint256) { + return 100; // 1.0.0 + } } diff --git a/contracts/DODOPrivatePool/impl/DPPStorage.sol b/contracts/DODOPrivatePool/impl/DPPStorage.sol index 21562af..2ad84fc 100644 --- a/contracts/DODOPrivatePool/impl/DPPStorage.sol +++ b/contracts/DODOPrivatePool/impl/DPPStorage.sol @@ -27,8 +27,8 @@ import {PMMPricing} from "../../lib/PMMPricing.sol"; contract DPPStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; - address public _FACTORY_; address public _ADMIN_; + address public _DODO_SMART_APPROVE_; // ============ Variables for Control ============ @@ -44,6 +44,7 @@ contract DPPStorage is InitializableOwnable, ReentrancyGuard { // ============ Core Address ============ address public _MAINTAINER_; // collect maintainer fee + address public _OPERATOR_; IERC20 public _BASE_TOKEN_; IERC20 public _QUOTE_TOKEN_; @@ -79,6 +80,10 @@ contract DPPStorage is InitializableOwnable, ReentrancyGuard { _MAINTAINER_ = newMaintainer; } + function setOperator(address newOperator) external onlyOwner { + _OPERATOR_ = newOperator; + } + function setGasPriceSource(address newGasPriceLimitSource) external onlyOwner { _GAS_PRICE_LIMIT_ = IExternalValue(newGasPriceLimitSource); } diff --git a/contracts/DODOPrivatePool/impl/DPPVault.sol b/contracts/DODOPrivatePool/impl/DPPVault.sol index a6f12c2..252d837 100644 --- a/contracts/DODOPrivatePool/impl/DPPVault.sol +++ b/contracts/DODOPrivatePool/impl/DPPVault.sol @@ -15,6 +15,7 @@ import {SafeMath} from "../../lib/SafeMath.sol"; import {DecimalMath} from "../../lib/DecimalMath.sol"; import {SafeERC20} from "../../lib/SafeERC20.sol"; import {Ownable} from "../../lib/Ownable.sol"; +import {ISmartApprove} from '../../intf/ISmartApprove.sol'; contract DPPVault is DPPStorage { using SafeMath for uint256; @@ -55,12 +56,6 @@ contract DPPVault is DPPStorage { _QUOTE_RESERVE_ = _QUOTE_TOKEN_.balanceOf(address(this)); } - //TODO: - function initTargetAndReserve() public { - require(tx.origin == _OWNER_, "INIT FORBIDDEN!"); - _resetTargetAndReserve(); - } - function _resetTargetAndReserve() internal { _BASE_TARGET_ = _BASE_TOKEN_.balanceOf(address(this)); _QUOTE_TARGET_ = _QUOTE_TOKEN_.balanceOf(address(this)); @@ -69,6 +64,7 @@ contract DPPVault is DPPStorage { } function reset( + address from, uint256 newLpFeeRate, uint256 newMtFeeRate, uint256 newI, @@ -76,11 +72,10 @@ contract DPPVault is DPPStorage { uint256 baseOutAmount, uint256 quoteOutAmount ) public { - //TODO: owner 权限可以是operator - require(tx.origin == _OWNER_, "RESET FORBIDDEN!"); + require(msg.sender == ISmartApprove(_DODO_SMART_APPROVE_).getSmartSwap() && from == _OPERATOR_, "RESET FORBIDDEN!"); require(newK > 0 && newK <= 10**18, "K OUT OF RANGE!"); - if(baseOutAmount > 0) _transferBaseOut(tx.origin, baseOutAmount); - if(quoteOutAmount > 0) _transferQuoteOut(tx.origin, quoteOutAmount); + if(baseOutAmount > 0) _transferBaseOut(from, baseOutAmount); + if(quoteOutAmount > 0) _transferQuoteOut(from, quoteOutAmount); _resetTargetAndReserve(); _LP_FEE_RATE_MODEL_.setFeeRate(newLpFeeRate); _MT_FEE_RATE_MODEL_.setFeeRate(newMtFeeRate); @@ -115,7 +110,7 @@ contract DPPVault is DPPStorage { uint256 amount ) external onlyOwner { require(to != address(_BASE_TOKEN_) && to != address(_QUOTE_TOKEN_), "USE_WITHDRAW"); - if (token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) { + if (token == 0x000000000000000000000000000000000000000E) { to.transfer(amount); } else { IERC20(token).safeTransfer(msg.sender, amount); diff --git a/contracts/DODOPrivatePool/intf/IDPP.sol b/contracts/DODOPrivatePool/intf/IDPP.sol index c42b5d2..54a467d 100644 --- a/contracts/DODOPrivatePool/intf/IDPP.sol +++ b/contracts/DODOPrivatePool/intf/IDPP.sol @@ -12,6 +12,7 @@ interface IDPP { function init( address owner, address maintainer, + address operator, address baseTokenAddress, address quoteTokenAddress, address lpFeeRateModel, @@ -19,6 +20,7 @@ interface IDPP { address kSource, address iSource, address gasPriceSource, + address dodoSmartApprove, address tradePermissionManager ) external; @@ -31,6 +33,8 @@ interface IDPP { function setMaintainer(address newMaintainer) external; + function setOperator(address newOperator) external; + function setGasPriceSource(address newGasPriceLimitSource) external; function setISource(address newISource) external; @@ -42,4 +46,6 @@ interface IDPP { function setSell(bool open) external; //============================== + function retrieve(address payable to,address token,uint256 amount) external; + } diff --git a/contracts/DODOVendingMachine/impl/DVM.sol b/contracts/DODOVendingMachine/impl/DVM.sol index 1bad01b..1034df7 100644 --- a/contracts/DODOVendingMachine/impl/DVM.sol +++ b/contracts/DODOVendingMachine/impl/DVM.sol @@ -17,10 +17,6 @@ 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, @@ -33,7 +29,6 @@ contract DVM is DVMTrader, DVMFunding { uint256 i, uint256 k ) external { - require(msg.sender == _FACTORY_, 'INIT FORBIDDEN'); initOwner(owner); _ADMIN_ = owner; _BASE_TOKEN_ = IERC20(baseTokenAddress); diff --git a/contracts/DODOVendingMachine/impl/DVMAdmin.sol b/contracts/DODOVendingMachine/impl/DVMAdmin.sol index 66203bb..ee57df5 100644 --- a/contracts/DODOVendingMachine/impl/DVMAdmin.sol +++ b/contracts/DODOVendingMachine/impl/DVMAdmin.sol @@ -47,4 +47,9 @@ contract DVMAdmin is InitializableOwnable { function setSell(bool open) external onlyOwner { IDVM(dvm).setSell(open); } + + // ============ Admin Version Control ============ + function version() external pure returns (uint256) { + return 100; // 1.0.0 + } } diff --git a/contracts/DODOVendingMachine/impl/DVMStorage.sol b/contracts/DODOVendingMachine/impl/DVMStorage.sol index 3be6516..bca6314 100644 --- a/contracts/DODOVendingMachine/impl/DVMStorage.sol +++ b/contracts/DODOVendingMachine/impl/DVMStorage.sol @@ -21,7 +21,6 @@ import {IERC20} from "../../intf/IERC20.sol"; contract DVMStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; - address public _FACTORY_; address public _ADMIN_; // ============ Variables for Control ============ @@ -63,8 +62,6 @@ contract DVMStorage is InitializableOwnable, ReentrancyGuard { uint256 public _I_; // ============ Setting Functions ============ - - //TODO: owner权限问题论证 function setLpFeeRateModel(address newLpFeeRateModel) external onlyOwner { _LP_FEE_RATE_MODEL_ = IFeeRateModel(newLpFeeRateModel); } diff --git a/contracts/Factory/DPPFactory.sol b/contracts/Factory/DPPFactory.sol index c376696..eeb4411 100644 --- a/contracts/Factory/DPPFactory.sol +++ b/contracts/Factory/DPPFactory.sol @@ -22,7 +22,9 @@ contract DPPFactory is Ownable { address public _DPP_ADMIN_TEMPLATE_; address public _FEE_RATE_MODEL_TEMPLATE_; address public _PERMISSION_MANAGER_TEMPLATE_; + address public _DEFAULT_GAS_PRICE_SOURCE_; address public _VALUE_SOURCE_; + address public _DODO_SMART_APPROVE_; //TODO: 平台修改tag的权限 && 池子标签类型 struct DPPInfo { @@ -31,13 +33,13 @@ contract DPPFactory is Ownable { } // base -> quote -> DPP address list - mapping(address => mapping(address => address[])) _REGISTRY_; + mapping(address => mapping(address => address[])) public _REGISTRY_; // token0 -> token1 -> DPP address list - mapping(address => mapping(address => address[])) _SORT_REGISTRY_; + mapping(address => mapping(address => address[])) public _SORT_REGISTRY_; // creator -> DPP address list - mapping(address => address[]) _USER_REGISTRY_; + mapping(address => address[]) public _USER_REGISTRY_; // DPP address -> info - mapping(address => DPPInfo) _DPP_INFO_; + mapping(address => DPPInfo) public _DPP_INFO_; constructor( address cloneFactory, @@ -45,7 +47,9 @@ contract DPPFactory is Ownable { address dppAdminTemplate, address defautFeeRateModelTemplate, address defaultPermissionManagerTemplate, - address defaultExternalValueTemplate + address defaultExternalValueTemplate, + address defaultGasPriceSource, + address dodoSmartApprove ) public { _CLONE_FACTORY_ = cloneFactory; _DPP_TEMPLATE_ = dppTemplate; @@ -53,40 +57,52 @@ contract DPPFactory is Ownable { _FEE_RATE_MODEL_TEMPLATE_ = defautFeeRateModelTemplate; _PERMISSION_MANAGER_TEMPLATE_ = defaultPermissionManagerTemplate; _VALUE_SOURCE_ = defaultExternalValueTemplate; + _DEFAULT_GAS_PRICE_SOURCE_ = defaultGasPriceSource; + _DODO_SMART_APPROVE_ = dodoSmartApprove; } - function createDODOPrivatePool( + function createDODOPrivatePool() external returns(address newPrivatePool) { + newPrivatePool = ICloneFactory(_CLONE_FACTORY_).clone(_DPP_TEMPLATE_); + } + + function initDODOPrivatePool( + address dppAddress, + address from, address baseToken, address quoteToken, uint256 lpFeeRate, uint256 mtFeeRate, - uint256 i, - uint256 k - ) external returns (address newPrivatePool) { - (address token0, address token1) = baseToken < quoteToken ? (baseToken, quoteToken) : (quoteToken, baseToken); - newPrivatePool = ICloneFactory(_CLONE_FACTORY_).clone(_DPP_TEMPLATE_); - - IDPP(newPrivatePool).init( - _createDPPAdminModel(msg.sender,newPrivatePool), - msg.sender, + uint256 k, + uint256 i + ) external { + { + address _dppAddress = dppAddress; + address adminModel = _createDPPAdminModel(from,_dppAddress); + IDPP(_dppAddress).init( + adminModel, + from, + from, baseToken, quoteToken, - _createFeeRateModel(newPrivatePool, lpFeeRate), - _createFeeRateModel(newPrivatePool, mtFeeRate), - _createExternalValueModel(newPrivatePool, k), - _createExternalValueModel(newPrivatePool, i), - //TODO:hardcode - _createExternalValueModel(msg.sender, 10**22), - //TODO:讨论 - _createPermissionManager(msg.sender) + _createFeeRateModel(_dppAddress, lpFeeRate), + _createFeeRateModel(_dppAddress, mtFeeRate), + _createExternalValueModel(_dppAddress, k), + _createExternalValueModel(_dppAddress, i), + _DEFAULT_GAS_PRICE_SOURCE_, + _DODO_SMART_APPROVE_, + _createPermissionManager(adminModel) ); + } - _REGISTRY_[baseToken][quoteToken].push(newPrivatePool); - _SORT_REGISTRY_[token0][token1].push(newPrivatePool); - _USER_REGISTRY_[msg.sender].push(newPrivatePool); - _DPP_INFO_[newPrivatePool] = ( + { + (address token0, address token1) = baseToken < quoteToken ? (baseToken, quoteToken) : (quoteToken, baseToken); + _SORT_REGISTRY_[token0][token1].push(dppAddress); + } + _REGISTRY_[baseToken][quoteToken].push(dppAddress); + _USER_REGISTRY_[from].push(dppAddress); + _DPP_INFO_[dppAddress] = ( DPPInfo({ - creator: msg.sender, + creator: from, createTimeStamp: block.timestamp }) ); @@ -112,8 +128,16 @@ contract DPPFactory is Ownable { IDPPAdmin(adminModel).init(owner,dpp); } - //TODO: 讨论 or 升级整个Factory function updateAdminTemplate(address _newDPPAdminTemplate) external onlyOwner { _DPP_ADMIN_TEMPLATE_ = _newDPPAdminTemplate; } + + + function getPrivatePool(address baseToken, address quoteToken) + external + view + returns (address[] memory pools) + { + return _REGISTRY_[baseToken][quoteToken]; + } } diff --git a/contracts/Factory/DVMFactory.sol b/contracts/Factory/DVMFactory.sol index 24fa89a..d01da4e 100644 --- a/contracts/Factory/DVMFactory.sol +++ b/contracts/Factory/DVMFactory.sol @@ -30,13 +30,13 @@ contract DVMFactory is Ownable { } // base -> quote -> DVM address list - mapping(address => mapping(address => address[])) _REGISTRY_; + mapping(address => mapping(address => address[])) public _REGISTRY_; // token0 -> token1 -> DVM address list - mapping(address => mapping(address => address[])) _SORT_REGISTRY_; + mapping(address => mapping(address => address[])) public _SORT_REGISTRY_; // creator -> DVM address list - mapping(address => address[]) _USER_REGISTRY_; + mapping(address => address[]) public _USER_REGISTRY_; // DVM address -> info - mapping(address => DVMInfo) _DVM_INFO_; + mapping(address => DVMInfo) public _DVM_INFO_; constructor( address cloneFactory, @@ -55,6 +55,7 @@ contract DVMFactory is Ownable { } function createDODOVendingMachine( + address from, address baseToken, address quoteToken, uint256 lpFeeRate, @@ -62,32 +63,34 @@ contract DVMFactory is Ownable { uint256 i, uint256 k ) external returns (address newVendingMachine) { - (address token0, address token1) = baseToken < quoteToken ? (baseToken, quoteToken) : (quoteToken, baseToken); newVendingMachine = ICloneFactory(_CLONE_FACTORY_).clone(_DVM_TEMPLATE_); - + { + address adminModel = _createDVMAdminModel(from,newVendingMachine); IDVM(newVendingMachine).init( - _createDVMAdminModel(msg.sender,newVendingMachine), - msg.sender, + adminModel, + from, baseToken, quoteToken, _createFeeRateModel(newVendingMachine, lpFeeRate), _createFeeRateModel(newVendingMachine, mtFeeRate), - _createPermissionManager(msg.sender), + _createPermissionManager(adminModel), _DEFAULT_GAS_PRICE_SOURCE_, i, k ); - + } _REGISTRY_[baseToken][quoteToken].push(newVendingMachine); + { + (address token0, address token1) = baseToken < quoteToken ? (baseToken, quoteToken) : (quoteToken, baseToken); _SORT_REGISTRY_[token0][token1].push(newVendingMachine); - _USER_REGISTRY_[msg.sender].push(newVendingMachine); + } + _USER_REGISTRY_[from].push(newVendingMachine); _DVM_INFO_[newVendingMachine] = ( DVMInfo({ - creator: msg.sender, + creator: from, createTimeStamp: block.timestamp }) ); - return newVendingMachine; } function _createFeeRateModel(address owner, uint256 feeRate) internal returns (address feeRateModel) { @@ -105,7 +108,6 @@ contract DVMFactory is Ownable { IDVMAdmin(adminModel).init(owner,dvm); } - //TODO: 讨论 or 升级整个Factory function updateAdminTemplate(address _newDVMAdminTemplate) external onlyOwner { _DVM_ADMIN_TEMPLATE_ = _newDVMAdminTemplate; } diff --git a/contracts/SmartRoute/DODOV2Proxy01.sol b/contracts/SmartRoute/DODOV2Proxy01.sol index ddd0f4e..f5b4cd5 100644 --- a/contracts/SmartRoute/DODOV2Proxy01.sol +++ b/contracts/SmartRoute/DODOV2Proxy01.sol @@ -19,7 +19,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { using SafeMath for uint256; using UniversalERC20 for IERC20; - address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + address constant ETH_ADDRESS = 0x000000000000000000000000000000000000000E; address payable public _WETH_; address public smartApprove; address public dodoSellHelper; @@ -44,8 +44,6 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { event ExternalRecord(address indexed to, address indexed sender); //======================================================================== - - constructor( address _dvmFactory, address _dppFactory, @@ -73,7 +71,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { uint256 deadline ) external virtual override payable judgeExpired(deadline) returns (address newVendingMachine,uint256 shares) { require(k > 0 && k<= 10**18, "DODOV2Proxy01: K OUT OF RANGE"); - newVendingMachine = IDODOV2(dvmFactory).createDODOVendingMachine(baseToken,quoteToken,lpFeeRate,mtFeeRate,i,k); + newVendingMachine = IDODOV2(dvmFactory).createDODOVendingMachine(msg.sender, baseToken,quoteToken,lpFeeRate,mtFeeRate,i,k); if(baseInAmount > 0) IDODOV2(smartApprove).claimTokens(baseToken, msg.sender, newVendingMachine, baseInAmount); if(quoteInAmount > 0) @@ -156,12 +154,21 @@ contract DODOV2Proxy01 is IDODOV2Proxy01 { uint256 k, uint256 deadline ) external virtual override payable judgeExpired(deadline) returns (address newPrivatePool) { - newPrivatePool = IDODOV2(dppFactory).createDODOPrivatePool(baseToken, quoteToken, lpFeeRate, mtFeeRate, i, k); + newPrivatePool = IDODOV2(dppFactory).createDODOPrivatePool(); if(baseInAmount > 0) IDODOV2(smartApprove).claimTokens(baseToken, msg.sender, newPrivatePool, baseInAmount); if(quoteInAmount > 0) IDODOV2(smartApprove).claimTokens(quoteToken, msg.sender, newPrivatePool, quoteInAmount); - IDODOV2(newPrivatePool).initTargetAndReserve(); + IDODOV2(dppFactory).initDODOPrivatePool( + newPrivatePool, + msg.sender, + baseToken, + quoteToken, + lpFeeRate, + mtFeeRate, + k, + i + ); } //TODO:ETH diff --git a/contracts/SmartRoute/SmartSwap.sol b/contracts/SmartRoute/SmartSwap01.sol similarity index 73% rename from contracts/SmartRoute/SmartSwap.sol rename to contracts/SmartRoute/SmartSwap01.sol index 9f00242..8139a20 100644 --- a/contracts/SmartRoute/SmartSwap.sol +++ b/contracts/SmartRoute/SmartSwap01.sol @@ -12,17 +12,22 @@ import {IERC20} from "../intf/IERC20.sol"; import {UniversalERC20} from "../lib/UniversalERC20.sol"; import {SafeMath} from "../lib/SafeMath.sol"; import {IDODOSellHelper} from "../intf/IDODOSellHelper.sol"; -import {ISmartApprove} from "../intf/ISmartApprove.sol"; import {IDODO} from "../intf/IDODO.sol"; import {IWETH} from "../intf/IWETH.sol"; +interface ISmartApprove { + function claimTokens(IERC20 token,address who,address dest,uint256 amount) external; + function getSmartSwap() external view returns (address); +} + + contract SmartSwap is Ownable { using SafeMath for uint256; using UniversalERC20 for IERC20; - address constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public smartApprove; - address public dodoSellHelper; + IERC20 constant ETH_ADDRESS = IERC20(0x000000000000000000000000000000000000000E); + ISmartApprove public smartApprove; + IDODOSellHelper public dodoSellHelper; address payable public _WETH_; @@ -32,8 +37,8 @@ contract SmartSwap is Ownable { } event OrderHistory( - address indexed fromToken, - address indexed toToken, + IERC20 indexed fromToken, + IERC20 indexed toToken, address indexed sender, uint256 fromAmount, uint256 returnAmount, @@ -45,8 +50,8 @@ contract SmartSwap is Ownable { address _dodoSellHelper, address payable _weth ) public { - smartApprove = _smartApprove; - dodoSellHelper = _dodoSellHelper; + smartApprove = ISmartApprove(_smartApprove); + dodoSellHelper = IDODOSellHelper(_dodoSellHelper); _WETH_ = _weth; } @@ -55,8 +60,8 @@ contract SmartSwap is Ownable { receive() external payable {} function dodoSwap( - address fromToken, - address toToken, + IERC20 fromToken, + IERC20 toToken, uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, @@ -67,7 +72,7 @@ contract SmartSwap is Ownable { require(dodoPairs.length > 0, "DODO SmartSwap: pairs should exists."); if (fromToken != ETH_ADDRESS) { - ISmartApprove(smartApprove).claimTokens(fromToken, msg.sender, address(this),fromTokenAmount); + smartApprove.claimTokens(fromToken, msg.sender, address(this),fromTokenAmount); } else { require(msg.value == fromTokenAmount, "DODO SmartSwap: ETH_AMOUNT_NOT_MATCH"); IWETH(_WETH_).deposit{value: fromTokenAmount}(); @@ -84,33 +89,32 @@ contract SmartSwap is Ownable { address curDodoQuote = IDODO(curDodoPair)._QUOTE_TOKEN_(); uint256 curAmountIn = IERC20(curDodoQuote).balanceOf(address(this)); IERC20(curDodoQuote).universalApprove(curDodoPair, curAmountIn); - uint256 canBuyBaseAmount = IDODOSellHelper(dodoSellHelper).querySellQuoteToken( + uint256 canBuyBaseAmount = dodoSellHelper.querySellQuoteToken( curDodoPair, curAmountIn ); IDODO(curDodoPair).buyBaseToken(canBuyBaseAmount, curAmountIn, ""); } } - IERC20(fromToken).universalTransfer(msg.sender, IERC20(fromToken).universalBalanceOf(address(this))); + fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); if (toToken == ETH_ADDRESS) { uint256 wethAmount = IWETH(_WETH_).balanceOf(address(this)); IWETH(_WETH_).withdraw(wethAmount); } - returnAmount = IERC20(toToken).universalBalanceOf(address(this)); + returnAmount = toToken.universalBalanceOf(address(this)); require(returnAmount >= minReturnAmount, "DODO SmartSwap: Return amount is not enough"); - IERC20(toToken).universalTransfer(msg.sender, returnAmount); + toToken.universalTransfer(msg.sender, returnAmount); emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount, block.timestamp); } function externalSwap( - address fromToken, - address toToken, + IERC20 fromToken, + IERC20 toToken, address approveTarget, address to, - uint256 gasSwap, uint256 fromTokenAmount, uint256 minReturnAmount, bytes memory callDataConcat, @@ -120,21 +124,21 @@ contract SmartSwap is Ownable { require(minReturnAmount > 0, "DODO SmartSwap: Min return should be bigger then 0."); if (fromToken != ETH_ADDRESS) { - ISmartApprove(smartApprove).claimTokens(fromToken, msg.sender, address(this), fromTokenAmount); - IERC20(fromToken).universalApprove(approveTarget, fromTokenAmount); + smartApprove.claimTokens(fromToken, msg.sender, address(this), fromTokenAmount); + fromToken.universalApprove(approveTarget, fromTokenAmount); } - (bool success, ) = to.call{value: fromToken == ETH_ADDRESS ? msg.value : 0, gas: gasSwap}( + (bool success, ) = to.call{value: fromToken == ETH_ADDRESS ? msg.value : 0}( callDataConcat ); require(success, "DODO SmartSwap: Contract Swap execution Failed"); - IERC20(fromToken).universalTransfer(msg.sender, IERC20(fromToken).universalBalanceOf(address(this))); - returnAmount = IERC20(toToken).universalBalanceOf(address(this)); + fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); + returnAmount = toToken.universalBalanceOf(address(this)); require(returnAmount >= minReturnAmount, "DODO SmartSwap: Return amount is not enough"); - IERC20(toToken).universalTransfer(msg.sender, returnAmount); + toToken.universalTransfer(msg.sender, returnAmount); emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount, block.timestamp); } } diff --git a/contracts/intf/IDODOV2.sol b/contracts/intf/IDODOV2.sol index c2f7ee3..76656ff 100644 --- a/contracts/intf/IDODOV2.sol +++ b/contracts/intf/IDODOV2.sol @@ -27,6 +27,7 @@ interface IDODOV2 { //========== DODOVendingMachine ======== function createDODOVendingMachine( + address from, address baseToken, address quoteToken, uint256 lpFeeRate, @@ -41,16 +42,18 @@ interface IDODOV2 { //========== DODOPrivatePool =========== - function initTargetAndReserve() external; + function createDODOPrivatePool() external returns (address newPrivatePool); - function createDODOPrivatePool( + function initDODOPrivatePool( + address dppAddress, + address from, address baseToken, address quoteToken, uint256 lpFeeRate, uint256 mtFeeRate, - uint256 i, - uint256 k - ) external returns (address newPrivatePool); + uint256 k, + uint256 i + ) external; function reset( uint256 newLpFeeRate, diff --git a/contracts/lib/UniversalERC20.sol b/contracts/lib/UniversalERC20.sol index 1d7534a..c85f1e9 100644 --- a/contracts/lib/UniversalERC20.sol +++ b/contracts/lib/UniversalERC20.sol @@ -16,7 +16,7 @@ library UniversalERC20 { using SafeERC20 for IERC20; IERC20 private constant ZERO_ADDRESS = IERC20(0x0000000000000000000000000000000000000000); - IERC20 private constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); + IERC20 private constant ETH_ADDRESS = IERC20(0x000000000000000000000000000000000000000E); function isETH(IERC20 token) internal pure returns (bool) { return (token == ZERO_ADDRESS || token == ETH_ADDRESS); diff --git a/migrations/1_initial_migration.js b/migrations/1_initial_migration.js index 16a7ba5..3439329 100644 --- a/migrations/1_initial_migration.js +++ b/migrations/1_initial_migration.js @@ -1,5 +1,5 @@ const Migrations = artifacts.require("Migrations"); module.exports = function (deployer) { - deployer.deploy(Migrations); + // deployer.deploy(Migrations); }; diff --git a/migrations/2_deploy.js b/migrations/2_deploy.js index 5b4af25..8c8c622 100644 --- a/migrations/2_deploy.js +++ b/migrations/2_deploy.js @@ -21,7 +21,7 @@ module.exports = async (deployer, network, accounts) => { DODOSellHelperAddress = "0xbdEae617F2616b45DCB69B287D52940a76035Fe3"; DODOZooAddress = "0x92230e929a2226b29ed3441ae5524886347c60c8"; WETHAddress = "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b"; - SmartApproveAddress = ""; + SmartApproveAddress = "0x5627b7DEb3055e1e899003FDca0716b32C382084"; } else if (network == "live") { DODOSellHelperAddress = "0x533da777aedce766ceae696bf90f8541a4ba80eb"; DODOZooAddress = "0x3a97247df274a17c59a3bd12735ea3fcdfb49950"; @@ -53,9 +53,9 @@ module.exports = async (deployer, network, accounts) => { ); logger.log("SmartSwap Address: ", SmartSwap.address); - const SmartApproveInstance = await SmartApprove.at(SmartApproveAddress); - var tx = await SmartApproveInstance.setSmartSwap(SmartSwap.address); - logger.log("SmartApprovce setSmartSwap tx: ", tx.tx); + // const SmartApproveInstance = await SmartApprove.at(SmartApproveAddress); + // var tx = await SmartApproveInstance.setSmartSwap(SmartSwap.address); + // logger.log("SmartApprovce setSmartSwap tx: ", tx.tx); } if (DEPLOY_KOVAN_TOKEN) { diff --git a/route-test.sh b/route-test.sh deleted file mode 100644 index 89655ff..0000000 --- a/route-test.sh +++ /dev/null @@ -1,2 +0,0 @@ -truffle compile --all -truffle test ./test/Route/Route.test.ts \ No newline at end of file diff --git a/test/Proxy/proxy.dpp.test.ts b/test/Proxy/proxy.dpp.test.ts new file mode 100644 index 0000000..273ef13 --- /dev/null +++ b/test/Proxy/proxy.dpp.test.ts @@ -0,0 +1,161 @@ +/* + + 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.WETH.methods.deposit().send(ctx.sendParam(lp, '80')); + // await ctx.WETH.methods.deposit().send(ctx.sendParam(project, '80')); +} + + +async function initCreateDPP(ctx: ProxyContext, token0: any, token1:any, token0Amount: string, token1Amount: string): Promise { + let PROXY = ctx.DODOProxy; + 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)); +} + +describe("DODOProxyV2.0", () => { + let snapshotId: string; + let ctx: ProxyContext; + + before(async () => { + ctx = await getProxyContext(); + await init(ctx); + // 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 DPP + * 3. 创建ETH && ERC20 Token + */ + it("createDPP - empty", async () => { + var baseToken = ctx.DODO.options.address; + var quoteToken = ctx.USDT.options.address; + await ctx.DODOProxy.methods.createDODOPrivatePool( + baseToken, + quoteToken, + decimalStr("0"), + decimalStr("0"), + config.lpFeeRate, + config.mtFeeRate, + config.i, + config.k, + Math.floor(new Date().getTime()/1000 + 60 * 10) + ).send(ctx.sendParam(project)); + var addrs = await ctx.DPPFactory.methods.getPrivatePool(baseToken,quoteToken).call(); + var dppInfo = await ctx.DPPFactory.methods._DPP_INFO_(addrs[0]).call(); + console.log("dppInfo:",dppInfo); + assert.equal( + dppInfo[0], + project + ); + }); + + + it("resetDPP", async () => { + //需要存钱 + //需要退钱 + }); + + + /** + * trade + */ + it("trade-sellQuote-R=1", async () => { + //R变号与不变号 + }); + + + it("trade-sellQuote-R>1", async () => { + //R变号与不变号 + }); + + + it("trade-sellQuote-R<1", async () => { + //R变号与不变号 + }); + + + it("trade-sellBase-R=1", async () => { + //R变号与不变号 + }); + + + it("trade-sellBase-R>1", async () => { + //R变号与不变号 + }); + + + it("trade-sellBase-R<1", async () => { + //R变号与不变号 + }); + + + + it("retrieve", async () => { + //eth允许 + //控制无法提取base && quote + }); + + + /** + * 直接底层dpp操作测试 + */ + + }); +}); diff --git a/test/Proxy/proxy.test.ts b/test/Proxy/proxy.dvm.test.ts similarity index 62% rename from test/Proxy/proxy.test.ts rename to test/Proxy/proxy.dvm.test.ts index 45daa09..6266de6 100644 --- a/test/Proxy/proxy.test.ts +++ b/test/Proxy/proxy.dvm.test.ts @@ -38,15 +38,13 @@ async function init(ctx: ProxyContext): Promise { 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")); + // await ctx.WETH.methods.deposit().send(ctx.sendParam(lp, '80')); + // await ctx.WETH.methods.deposit().send(ctx.sendParam(project, '80')); } 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( + await PROXY.methods.createDODOVendingMachine( token0.options.address, token1.options.address, token0Amount, @@ -57,26 +55,8 @@ async function initCreateDVM(ctx: ProxyContext, token0: any, token1:any, token0A 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; @@ -85,10 +65,8 @@ describe("DODOProxyV2.0", () => { 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")); + // await initCreateDVM(ctx,ctx.DODO,ctx.USDT,decimalStr("10000"),decimalStr("10000")); + // await initCreateDVM(ctx,ctx.WETH,ctx.USDT,decimalStr("50"),decimalStr("10000")); }); beforeEach(async () => { @@ -126,24 +104,6 @@ describe("DODOProxyV2.0", () => { }); - /** - * 1. 创建空池子 - * 2. 创建ERC20 DPP - * 3. 创建ETH && ERC20 Token - */ - it("createDPP", async () => { - - }); - - - /** - * - */ - it("resetDPP", async () => { - - }); - - /** * */ @@ -151,5 +111,11 @@ describe("DODOProxyV2.0", () => { }); + + + /** + * 直接底层dvm操作测试 + */ + }); }); diff --git a/test/Route/Route.test.ts b/test/Route/Route.test.ts index 20126db..0e21924 100644 --- a/test/Route/Route.test.ts +++ b/test/Route/Route.test.ts @@ -90,7 +90,7 @@ async function calcRoute(ctx: DODOContext, fromTokenAmount: string, slippage: nu let curPair = pairs[i] dodoPairs.push(curPair.pair) let curContact = pairs[i].pairContract - if (routes[i].address == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') { + if (routes[i].address == '0x000000000000000000000000000000000000000E') { directions[i] = 0; swapAmount = await curContact.methods.querySellBaseToken(swapAmount).call(); console.log(i + "-swapAmount:", swapAmount); @@ -273,7 +273,7 @@ describe("Trader", () => { console.log("weth contract Before:" + fromWei(b_w_eth, 'ether')) //set route path var routes = [{ - address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + address: "0x000000000000000000000000000000000000000E", decimals: 18 }, { address: ctx.USDC.options.address, @@ -311,7 +311,7 @@ describe("Trader", () => { console.log("weth contract Before:" + fromWei(b_w_eth, 'ether')) //set route path var routes = [{ - address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + address: "0x000000000000000000000000000000000000000E", decimals: 18 }, { address: ctx.USDC.options.address, @@ -368,7 +368,7 @@ describe("Trader", () => { address: ctx.USDC.options.address, decimals: 6 }, { - address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + address: "0x000000000000000000000000000000000000000E", decimals: 18 }]; diff --git a/test/utils/Contracts.ts b/test/utils/Contracts.ts index 1236a82..522bd4d 100644 --- a/test/utils/Contracts.ts +++ b/test/utils/Contracts.ts @@ -21,7 +21,7 @@ export const DODO_LP_TOKEN_CONTRACT_NAME = "DODOLpToken" export const DODO_ZOO_CONTRACT_NAME = "DOOZoo" export const DODO_WILD_CONTRACT_NAME = "DOOWild" export const DODO_ETH_PROXY_CONTRACT_NAME = "DODOEthProxy" -export const WETH_CONTRACT_NAME = "WETH" +export const WETH_CONTRACT_NAME = "WETH9" export const UNISWAP_CONTRACT_NAME = "Uniswap" export const UNISWAP_ARBITRAGEUR_CONTRACT_NAME = "UniswapArbitrageur" export const DODO_TOKEN_CONTRACT_NAME = "DODOToken" diff --git a/test/utils/Converter.ts b/test/utils/Converter.ts index 53edd17..e01ac5d 100644 --- a/test/utils/Converter.ts +++ b/test/utils/Converter.ts @@ -12,4 +12,4 @@ export function gweiStr(gwei: string): string { 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 +} \ No newline at end of file diff --git a/test/utils/ProxyContext.ts b/test/utils/ProxyContext.ts index 945ca5d..d7d1a10 100644 --- a/test/utils/ProxyContext.ts +++ b/test/utils/ProxyContext.ts @@ -43,6 +43,11 @@ export class ProxyContext { this.EVM = new EVM(); this.Web3 = getDefaultWeb3(); + const allAccounts = await this.Web3.eth.getAccounts(); + this.Deployer = allAccounts[0]; + this.Maintainer = allAccounts[1]; + this.SpareAccounts = allAccounts.slice(2, 10); + var WETH = await contracts.newContract( contracts.WETH_CONTRACT_NAME ); @@ -57,6 +62,8 @@ export class ProxyContext { 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) + var defaultGasSource = await contracts.newContract(contracts.EXTERNAL_VALUE_NAME) + await defaultGasSource.methods.init(this.Deployer,decimalStr("1000000")); this.DVMFactory = await contracts.newContract(contracts.DVM_FACTORY_NAME, [ @@ -65,10 +72,14 @@ export class ProxyContext { dvmAdminTemplate.options.address, feeRateModelTemplate.options.address, permissionManagerTemplate.options.address, - vauleSource.options.address + defaultGasSource.options.address ] ) + this.SmartApprove = await contracts.newContract( + contracts.SMART_APPROVE + ); + this.DPPFactory = await contracts.newContract(contracts.DPP_FACTORY_NAME, [ cloneFactory.options.address, @@ -76,28 +87,28 @@ export class ProxyContext { dppAdminTemplate.options.address, feeRateModelTemplate.options.address, permissionManagerTemplate.options.address, - vauleSource.options.address + vauleSource.options.address, + defaultGasSource.options.address, + this.SmartApprove.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, + this.DVMFactory.options.address, + this.DPPFactory.options.address, WETH.options.address, - smartApprove.options.address, + this.SmartApprove.options.address, dodoSellHelper.options.address ] ); + await this.SmartApprove.methods.setSmartSwap(this.DODOProxy.options.address).send(this.sendParam(this.Deployer)); + this.DODO = await contracts.newContract( contracts.MINTABLE_ERC20_CONTRACT_NAME, ["DODO Token", "DODO", 18] @@ -110,11 +121,6 @@ export class ProxyContext { 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]")); } diff --git a/truffle-config.js b/truffle-config.js index fbe8759..4108552 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -68,7 +68,7 @@ module.exports = { return new HDWalletProvider(privKey, "https://mainnet.infura.io/v3/" + infuraId); }, gas: 3000000, - gasPrice: 60000000000, + gasPrice: 120000000000, network_id: 1, skipDryRun: true }, diff --git a/truffle-test.sh b/truffle-test.sh new file mode 100644 index 0000000..5843314 --- /dev/null +++ b/truffle-test.sh @@ -0,0 +1,19 @@ +#!/bin/bash +truffle compile --all + +if [ "$1"x = "proxy-dpp"x ] +then + truffle test ./test/Proxy/proxy.dpp.test.ts +fi + +if [ "$1"x = "proxy-dvm"x ] +then + truffle test ./test/Proxy/proxy.dvm.test.ts +fi + +if [ "$1"x = "route"x ] +then + truffle test ./test/Route/route.test.ts +fi + + \ No newline at end of file