diff --git a/contracts/CrowdPooling/impl/CP.sol b/contracts/CrowdPooling/impl/CP.sol index db40ec3..94d2553 100644 --- a/contracts/CrowdPooling/impl/CP.sol +++ b/contracts/CrowdPooling/impl/CP.sol @@ -14,6 +14,12 @@ import {IPermissionManager} from "../../lib/PermissionManager.sol"; import {IFeeRateModel} from "../../lib/FeeRateModel.sol"; import {SafeMath} from "../../lib/SafeMath.sol"; +/** + * @title DODO CrowdPooling + * @author DODO Breeder + * + * @notice CrowdPooling initialization + */ contract CP is CPVesting { using SafeMath for uint256; diff --git a/contracts/CrowdPooling/impl/CPFunding.sol b/contracts/CrowdPooling/impl/CPFunding.sol index 4f21408..4d39cbe 100644 --- a/contracts/CrowdPooling/impl/CPFunding.sol +++ b/contracts/CrowdPooling/impl/CPFunding.sol @@ -16,15 +16,18 @@ import {IDVM} from "../../DODOVendingMachine/intf/IDVM.sol"; import {IDVMFactory} from "../../Factory/DVMFactory.sol"; import {CPStorage} from "./CPStorage.sol"; import {PMMPricing} from "../../lib/PMMPricing.sol"; +import {IDODOCallee} from "../../intf/IDODOCallee.sol"; contract CPFunding is CPStorage { using SafeERC20 for IERC20; + // ============ Events ============ + event Bid(address to, uint256 amount, uint256 fee); event Cancel(address to,uint256 amount); // ============ BID & CALM PHASE ============ - + modifier isBidderAllow(address bidder) { require(_BIDDER_PERMISSION_.isAllowed(bidder), "BIDDER_NOT_ALLOWED"); _; @@ -39,12 +42,17 @@ contract CPFunding is CPStorage { emit Bid(to, input, mtFee); } - function cancel(address assetTo, uint256 amount) external phaseBidOrCalm preventReentrant { + function cancel(address to, uint256 amount, bytes calldata data) external phaseBidOrCalm preventReentrant { require(_SHARES_[msg.sender] >= amount, "SHARES_NOT_ENOUGH"); _burnShares(msg.sender, amount); - _transferQuoteOut(assetTo, amount); + _transferQuoteOut(to, amount); _sync(); - emit Cancel(assetTo,amount); + + if(data.length > 0){ + IDODOCallee(to).CPCancelCall(msg.sender,amount,data); + } + + emit Cancel(msg.sender,amount); } function _mintShares(address to, uint256 amount) internal { @@ -66,9 +74,10 @@ contract CPFunding is CPStorage { _UNUSED_QUOTE_ = _QUOTE_TOKEN_.balanceOf(address(this)).sub(poolQuote); _UNUSED_BASE_ = _BASE_TOKEN_.balanceOf(address(this)).sub(poolBase); - // 这里的目的是让midPrice尽量等于avgPrice - // 我们统一设定k=1,如果quote和base不平衡,就必然要截断一边 - // DVM截断了quote,所以如果进入池子的quote很多,就要把quote设置成DVM的base + // Try to make midPrice equal to avgPrice + // k=1, If quote and base are not balanced, one side must be cut off + // DVM truncated quote, but if more quote than base entering the pool, we need set the quote to the base + // m = avgPrice // i = m (1-quote/(m*base)) // if quote = m*base i = 1 @@ -88,18 +97,18 @@ contract CPFunding is CPStorage { _poolBaseToken = address(_BASE_TOKEN_); _poolQuoteToken = address(_QUOTE_TOKEN_); _poolI = _I_; - } else if (poolQuote.mul(_UNUSED_BASE_) == poolQuote.mul(poolBase)) { + } else if (_UNUSED_BASE_== poolBase) { // standard bonding curve _poolBaseToken = address(_BASE_TOKEN_); _poolQuoteToken = address(_QUOTE_TOKEN_); _poolI = 1; - } else if (poolQuote.mul(_UNUSED_BASE_) < poolQuote.mul(poolBase)) { + } else if (_UNUSED_BASE_ < poolBase) { // poolI up round _poolBaseToken = address(_BASE_TOKEN_); _poolQuoteToken = address(_QUOTE_TOKEN_); uint256 ratio = DecimalMath.ONE.sub(DecimalMath.divFloor(poolQuote, baseDepth)); _poolI = avgPrice.mul(ratio).mul(ratio).divCeil(DecimalMath.ONE2); - } else if (poolQuote.mul(_UNUSED_BASE_) > poolQuote.mul(poolBase)) { + } else if (_UNUSED_BASE_ > poolBase) { // poolI down round _poolBaseToken = address(_QUOTE_TOKEN_); _poolQuoteToken = address(_BASE_TOKEN_); @@ -129,7 +138,6 @@ contract CPFunding is CPStorage { require(block.timestamp >= _PHASE_CALM_ENDTIME_.add(_SETTLEMENT_EXPIRE_), "NOT_EMERGENCY"); _settle(); _UNUSED_QUOTE_ = _QUOTE_TOKEN_.balanceOf(address(this)); - _UNUSED_BASE_ = _BASE_TOKEN_.balanceOf(address(this)); } function _settle() internal { @@ -194,8 +202,6 @@ contract CPFunding is CPStorage { } } - // ============ Asset Out ============ - function getShares(address user) external view returns (uint256) { return _SHARES_[user]; } diff --git a/contracts/CrowdPooling/impl/CPStorage.sol b/contracts/CrowdPooling/impl/CPStorage.sol index 7be9580..a788e84 100644 --- a/contracts/CrowdPooling/impl/CPStorage.sol +++ b/contracts/CrowdPooling/impl/CPStorage.sol @@ -18,6 +18,8 @@ import {IERC20} from "../../intf/IERC20.sol"; contract CPStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; + // ============ Constant ============ + uint256 internal constant _SETTLEMENT_EXPIRE_ = 86400 * 7; uint256 internal constant _SETTEL_FUND_ = 200 finney; diff --git a/contracts/CrowdPooling/impl/CPVesting.sol b/contracts/CrowdPooling/impl/CPVesting.sol index 4988a24..6810ccf 100644 --- a/contracts/CrowdPooling/impl/CPVesting.sol +++ b/contracts/CrowdPooling/impl/CPVesting.sol @@ -14,6 +14,7 @@ import {Ownable} from "../../lib/Ownable.sol"; import {SafeERC20} from "../../lib/SafeERC20.sol"; import {IERC20} from "../../intf/IERC20.sol"; import {CPFunding} from "./CPFunding.sol"; +import {IDODOCallee} from "../../intf/IDODOCallee.sol"; /** * @title CPVesting @@ -26,6 +27,8 @@ contract CPVesting is CPFunding { using SafeMath for uint256; using SafeERC20 for IERC20; + // ================ Modifiers ================ + modifier afterSettlement() { require(_SETTLED_, "NOT_SETTLED"); _; @@ -38,12 +41,20 @@ contract CPVesting is CPFunding { // ============ Bidder Functions ============ - function bidderClaim() external afterSettlement { + function bidderClaim(address to,bytes calldata data) external afterSettlement { require(!_CLAIMED_[msg.sender], "ALREADY_CLAIMED"); _CLAIMED_[msg.sender] = true; - _transferBaseOut(msg.sender, _UNUSED_BASE_.mul(_SHARES_[msg.sender]).div(_TOTAL_SHARES_)); - _transferQuoteOut(msg.sender, _UNUSED_QUOTE_.mul(_SHARES_[msg.sender]).div(_TOTAL_SHARES_)); + uint256 baseAmount = _UNUSED_BASE_.mul(_SHARES_[msg.sender]).div(_TOTAL_SHARES_); + uint256 quoteAmount = _UNUSED_QUOTE_.mul(_SHARES_[msg.sender]).div(_TOTAL_SHARES_); + + _transferBaseOut(to, baseAmount); + _transferQuoteOut(to, quoteAmount); + + if(data.length>0){ + IDODOCallee(to).CPClaimBidCall(msg.sender,baseAmount,quoteAmount,data); + } + } // ============ Owner Functions ============ diff --git a/contracts/CrowdPooling/intf/ICP.sol b/contracts/CrowdPooling/intf/ICP.sol index b1193ba..86d6aa8 100644 --- a/contracts/CrowdPooling/intf/ICP.sol +++ b/contracts/CrowdPooling/intf/ICP.sol @@ -15,11 +15,6 @@ interface ICP { uint256[] calldata valueList ) external; - //============================== - - - //============================== - function bid(address to) external; function cancel(address assetTo, uint256 amount) external; diff --git a/contracts/DODOPrivatePool/impl/DPP.sol b/contracts/DODOPrivatePool/impl/DPP.sol index ddd7d16..dee0850 100644 --- a/contracts/DODOPrivatePool/impl/DPP.sol +++ b/contracts/DODOPrivatePool/impl/DPP.sol @@ -12,6 +12,12 @@ import {IFeeRateModel} from "../../lib/FeeRateModel.sol"; import {IERC20} from "../../intf/IERC20.sol"; import {DPPTrader} from "./DPPTrader.sol"; +/** + * @title DODO PrivatePool + * @author DODO Breeder + * + * @notice DODOPrivatePool initialization + */ contract DPP is DPPTrader { function init( address owner, diff --git a/contracts/DODOPrivatePool/impl/DPPAdmin.sol b/contracts/DODOPrivatePool/impl/DPPAdmin.sol index 506ba2c..24d26cb 100644 --- a/contracts/DODOPrivatePool/impl/DPPAdmin.sol +++ b/contracts/DODOPrivatePool/impl/DPPAdmin.sol @@ -12,13 +12,19 @@ import {IDPP} from "../intf/IDPP.sol"; import {IDODOApprove} from "../../intf/IDODOApprove.sol"; import {InitializableOwnable} from "../../lib/InitializableOwnable.sol"; +/** + * @title DPPAdmin + * @author DODO Breeder + * + * @notice Admin of DODOPrivatePool + */ contract DPPAdmin is InitializableOwnable { address public _DPP_; address public _OPERATOR_; address public _DODO_APPROVE_; - uint256 public _FREEZE_TIMESTAMP_; + modifier notFreezed() { require(block.timestamp >= _FREEZE_TIMESTAMP_, "ADMIN_FREEZED"); _; @@ -36,7 +42,6 @@ contract DPPAdmin is InitializableOwnable { _DODO_APPROVE_ = dodoApprove; } - //For Rebase Token function sync() external notFreezed onlyOwner { IDPP(_DPP_).ratioSync(); } diff --git a/contracts/DODOPrivatePool/impl/DPPStorage.sol b/contracts/DODOPrivatePool/impl/DPPStorage.sol index 4336d85..17754ca 100644 --- a/contracts/DODOPrivatePool/impl/DPPStorage.sol +++ b/contracts/DODOPrivatePool/impl/DPPStorage.sol @@ -16,12 +16,6 @@ import {IFeeRateModel} from "../../lib/FeeRateModel.sol"; import {IERC20} from "../../intf/IERC20.sol"; import {PMMPricing} from "../../lib/PMMPricing.sol"; -/** - * @title Storage - * @author DODO Breeder - * - * @notice Local Variables - */ contract DPPStorage is InitializableOwnable, ReentrancyGuard { using SafeMath for uint256; diff --git a/contracts/DODOPrivatePool/impl/DPPVault.sol b/contracts/DODOPrivatePool/impl/DPPVault.sol index 48dce43..fdb861f 100644 --- a/contracts/DODOPrivatePool/impl/DPPVault.sol +++ b/contracts/DODOPrivatePool/impl/DPPVault.sol @@ -83,22 +83,9 @@ contract DPPVault is DPPStorage { _QUOTE_RESERVE_ = uint128(quoteBalance); _BASE_TARGET_ = uint120(baseBalance); _QUOTE_TARGET_ = uint120(quoteBalance); - _setRState(); + _RState_ = uint16(PMMPricing.RState.ONE); } - function _setRState() internal { - if (_BASE_RESERVE_ == _BASE_TARGET_ && _QUOTE_RESERVE_ == _QUOTE_TARGET_) { - _RState_ = uint16(PMMPricing.RState.ONE); - } else if (_BASE_RESERVE_ > _BASE_TARGET_ && _QUOTE_RESERVE_ < _QUOTE_TARGET_) { - _RState_ = uint16(PMMPricing.RState.BELOW_ONE); - } else if (_BASE_RESERVE_ < _BASE_TARGET_ && _QUOTE_RESERVE_ > _QUOTE_TARGET_) { - _RState_ = uint16(PMMPricing.RState.ABOVE_ONE); - } else { - require(false, "R_STATE_WRONG"); - } - } - - function ratioSync() external preventReentrant onlyOwner { uint256 baseBalance = _BASE_TOKEN_.balanceOf(address(this)); uint256 quoteBalance = _QUOTE_TOKEN_.balanceOf(address(this)); @@ -115,13 +102,6 @@ contract DPPVault is DPPStorage { } } - function setTarget(uint256 baseTarget, uint256 quoteTarget) public preventReentrant onlyOwner { - require(baseTarget <= uint120(-1) && quoteTarget <= uint120(-1), "OVERFLOW"); - _BASE_TARGET_ = uint120(baseTarget); - _QUOTE_TARGET_ = uint120(quoteTarget); - _setRState(); - } - function reset( address assetTo, uint256 newLpFeeRate, diff --git a/contracts/DODOPrivatePool/intf/IDPP.sol b/contracts/DODOPrivatePool/intf/IDPP.sol index 1d3383e..70eda0c 100644 --- a/contracts/DODOPrivatePool/intf/IDPP.sol +++ b/contracts/DODOPrivatePool/intf/IDPP.sol @@ -25,8 +25,6 @@ interface IDPP { //=========== admin ========== function ratioSync() external; - //============================== - function retrieve( address payable to, address token, diff --git a/contracts/DODOVendingMachine/impl/DVM.sol b/contracts/DODOVendingMachine/impl/DVM.sol index d1134a9..5aa1c0b 100644 --- a/contracts/DODOVendingMachine/impl/DVM.sol +++ b/contracts/DODOVendingMachine/impl/DVM.sol @@ -14,6 +14,12 @@ import {DVMTrader} from "./DVMTrader.sol"; import {DVMFunding} from "./DVMFunding.sol"; import {DVMVault} from "./DVMVault.sol"; +/** + * @title DODO VendingMachine + * @author DODO Breeder + * + * @notice DODOVendingMachine initialization + */ contract DVM is DVMTrader, DVMFunding { function init( address maintainer, @@ -76,6 +82,7 @@ contract DVM is DVMTrader, DVMFunding { } // ============ Version Control ============ + function version() external pure returns (string memory) { return "DVM 1.0.0"; } diff --git a/contracts/DODOVendingMachine/impl/DVMFunding.sol b/contracts/DODOVendingMachine/impl/DVMFunding.sol index 2ecbf64..c4d9630 100644 --- a/contracts/DODOVendingMachine/impl/DVMFunding.sol +++ b/contracts/DODOVendingMachine/impl/DVMFunding.sol @@ -40,11 +40,10 @@ contract DVMFunding is DVMVault { quoteInput = quoteBalance.sub(quoteReserve); require(baseInput > 0, "NO_BASE_INPUT"); - // case 1. initial supply - // 包含了 baseReserve == 0 && quoteReserve == 0 的情况 - // 在提币的时候向下取整。因此永远不会出现,balance为0但totalsupply不为0的情况 - // 但有可能出现,reserve>0但totalSupply=0的场景 + // Round down when withdrawing. Therefore, never be a situation occuring balance is 0 but totalsupply is not 0 + // But May Happen,reserve >0 But totalSupply = 0 if (totalSupply == 0) { + // case 1. initial supply require(baseBalance >= 10**3, "INSUFFICIENT_LIQUIDITY_MINED"); shares = baseBalance; // 以免出现balance很大但shares很小的情况 } else if (baseReserve > 0 && quoteReserve == 0) { diff --git a/contracts/DODOVendingMachine/impl/DVMTrader.sol b/contracts/DODOVendingMachine/impl/DVMTrader.sol index 06722c2..98728e1 100644 --- a/contracts/DODOVendingMachine/impl/DVMTrader.sol +++ b/contracts/DODOVendingMachine/impl/DVMTrader.sol @@ -35,7 +35,7 @@ contract DVMTrader is DVMVault { uint256 quoteAmount ); - // ============ Execute ============ + // ============ Trade Functions ============ function sellBase(address to) external diff --git a/contracts/DODOVendingMachine/impl/DVMVault.sol b/contracts/DODOVendingMachine/impl/DVMVault.sol index 8246df4..80e3f77 100644 --- a/contracts/DODOVendingMachine/impl/DVMVault.sol +++ b/contracts/DODOVendingMachine/impl/DVMVault.sol @@ -179,6 +179,7 @@ contract DVMVault is DVMStorage { } // ============================ Permit ====================================== + function permit( address owner, address spender, @@ -205,5 +206,4 @@ contract DVMVault is DVMStorage { ); _approve(owner, spender, value); } - // =========================================================================== } diff --git a/contracts/Factory/CrowdPoolingFactory.sol b/contracts/Factory/CrowdPoolingFactory.sol index 5010bf9..b30fd23 100644 --- a/contracts/Factory/CrowdPoolingFactory.sol +++ b/contracts/Factory/CrowdPoolingFactory.sol @@ -15,6 +15,12 @@ import {SafeMath} from "../lib/SafeMath.sol"; import {IERC20} from "../intf/IERC20.sol"; import {DecimalMath} from "../lib/DecimalMath.sol"; +/** + * @title CrowdPoolingFacotry + * @author DODO Breeder + * + * @notice Create And Register CP Pools + */ contract CrowdPoolingFactory is InitializableOwnable { using SafeMath for uint256; // ============ Templates ============ @@ -27,6 +33,7 @@ contract CrowdPoolingFactory is InitializableOwnable { address public _CP_TEMPLATE_; // ============ Settings ============= + uint256 public _CAP_RATIO_ = 50; uint256 public _FREEZE_DURATION_ = 30 days; uint256 public _CALM_DURATION_ = 0; @@ -43,6 +50,7 @@ contract CrowdPoolingFactory is InitializableOwnable { mapping(address => address[]) public _USER_REGISTRY_; // ============ modifiers =========== + modifier valueCheck( address cpAddress, address baseToken, @@ -55,7 +63,7 @@ contract CrowdPoolingFactory is InitializableOwnable { require(valueList[3] == _CLIFF_RATE_, "CP_FACTORY : CLIFF_RATE_INVALID"); uint256 baseTokenBalance = IERC20(baseToken).balanceOf(cpAddress); - require(valueList[0].mul(100) <= baseTokenBalance.mul(valueList[2]).div(10**18).mul(_CAP_RATIO_),"CP_FACTORY : QUOTE_CAPE_INVALID"); + require(valueList[0].mul(100) <= baseTokenBalance.mul(valueList[2]).div(10**18).mul(_CAP_RATIO_),"CP_FACTORY : QUOTE_CAP_INVALID"); require(timeLine[3]>= _FREEZE_DURATION_, "CP_FACTORY : FREEZE_DURATION_INVALID"); _; } @@ -69,8 +77,6 @@ contract CrowdPoolingFactory is InitializableOwnable { address cp ); - // ============ Functions ============ - constructor( address cloneFactory, address cpTemplate, @@ -87,6 +93,8 @@ contract CrowdPoolingFactory is InitializableOwnable { _DEFAULT_PERMISSION_MANAGER_ = defaultPermissionManager; } + // ============ Functions ============ + function createCrowdPooling() external returns (address newCrowdPooling) { newCrowdPooling = ICloneFactory(_CLONE_FACTORY_).clone(_CP_TEMPLATE_); } @@ -149,6 +157,7 @@ contract CrowdPoolingFactory is InitializableOwnable { } // ============ Owner Functions ============ + function updateCPTemplate(address _newCPTemplate) external onlyOwner { _CP_TEMPLATE_ = _newCPTemplate; } diff --git a/contracts/Factory/DPPFactory.sol b/contracts/Factory/DPPFactory.sol index f1891ca..0f32f2f 100644 --- a/contracts/Factory/DPPFactory.sol +++ b/contracts/Factory/DPPFactory.sol @@ -14,6 +14,12 @@ import {IFeeRateModel} from "../lib/FeeRateModel.sol"; import {IDPP} from "../DODOPrivatePool/intf/IDPP.sol"; import {IDPPAdmin} from "../DODOPrivatePool/intf/IDPPAdmin.sol"; +/** + * @title DODO PrivatePool Factory + * @author DODO Breeder + * + * @notice Create And Register DPP Pools + */ contract DPPFactory is InitializableOwnable { // ============ Templates ============ @@ -43,8 +49,6 @@ contract DPPFactory is InitializableOwnable { event RemoveDPP(address dpp); - // ============ Functions ============ - constructor( address cloneFactory, address dppTemplate, @@ -61,6 +65,8 @@ contract DPPFactory is InitializableOwnable { _DODO_APPROVE_ = dodoApprove; } + // ============ Functions ============ + function createDODOPrivatePool() external returns (address newPrivatePool) { newPrivatePool = ICloneFactory(_CLONE_FACTORY_).clone(_DPP_TEMPLATE_); } diff --git a/contracts/Factory/DVMFactory.sol b/contracts/Factory/DVMFactory.sol index 2b091df..25b4d8a 100644 --- a/contracts/Factory/DVMFactory.sol +++ b/contracts/Factory/DVMFactory.sol @@ -22,6 +22,13 @@ interface IDVMFactory { ) external returns (address newVendingMachine); } + +/** + * @title DODO VendingMachine Factory + * @author DODO Breeder + * + * @notice Create And Register DVM Pools + */ contract DVMFactory is InitializableOwnable { // ============ Templates ============ diff --git a/contracts/Factory/ERC20Factory.sol b/contracts/Factory/ERC20Factory.sol index 7d409ef..cf6a0ab 100644 --- a/contracts/Factory/ERC20Factory.sol +++ b/contracts/Factory/ERC20Factory.sol @@ -12,6 +12,13 @@ import {ICloneFactory} from "../lib/CloneFactory.sol"; import {InitializableERC20} from "../external/ERC20/InitializableERC20.sol"; import {InitializableMintableERC20} from "../external/ERC20/InitializableMintableERC20.sol"; + +/** + * @title DODO ERC20Factory + * @author DODO Breeder + * + * @notice Help user to create erc20 token + */ contract ERC20Factory { // ============ Templates ============ diff --git a/contracts/SmartRoute/DODOIncentive.sol b/contracts/SmartRoute/DODOIncentive.sol index 4d40b05..3669aaf 100644 --- a/contracts/SmartRoute/DODOIncentive.sol +++ b/contracts/SmartRoute/DODOIncentive.sol @@ -40,10 +40,6 @@ contract DODOIncentive is InitializableOwnable { uint112 public totalReward; uint112 public totalDistribution; - constructor(address _dodoToken) public { - _DODO_TOKEN_ = _dodoToken; - } - // ============ Events ============ event SetBoost(address token, uint256 boostRate); @@ -53,6 +49,10 @@ contract DODOIncentive is InitializableOwnable { event SetDefaultRate(uint256 defaultRate); event Incentive(address user,uint256 reward); + constructor(address _dodoToken) public { + _DODO_TOKEN_ = _dodoToken; + } + // ============ Ownable ============ function switchIncentive(uint256 _startBlock) public onlyOwner { @@ -98,6 +98,7 @@ contract DODOIncentive is InitializableOwnable { // ============ Incentive function============ + function triggerIncentive(address fromToken,address toToken, address assetTo) external { require(msg.sender == _DODO_PROXY_, "DODOIncentive:Access restricted"); uint256 _startBlock = startBlock; @@ -106,14 +107,10 @@ contract DODOIncentive is InitializableOwnable { uint256 curTotalDistribution = totalDistribution; uint256 fromRate = boosts[fromToken]; uint256 toRate = boosts[toToken]; - // uint256 rate = (fromRate >= toRate ? fromRate : toRate).add(defaultRate); uint256 rate = (fromRate >= toRate ? fromRate : toRate) + defaultRate; - // uint256 _totalReward = uint256(totalReward).add(block.number.sub(uint256(lastRewardBlock)).mul(dodoPerBlock)); uint256 _totalReward = totalReward + (block.number - lastRewardBlock) * dodoPerBlock; - // uint256 reward = _totalReward.sub(curTotalDistribution).mul(rate).div(1000); uint256 reward = (_totalReward - curTotalDistribution) * rate / 1000; - // uint256 _totalDistribution = curTotalDistribution.add(reward); uint256 _totalDistribution = curTotalDistribution + reward; _update(_totalReward,_totalDistribution); @@ -125,7 +122,6 @@ contract DODOIncentive is InitializableOwnable { function _update(uint256 _totalReward, uint256 _totalDistribution) internal { if(_totalReward == 0) - // _totalReward = uint256(totalReward).add(block.number.sub(uint256(lastRewardBlock)).mul(dodoPerBlock)); _totalReward = totalReward + (block.number - lastRewardBlock) * dodoPerBlock; require(_totalReward < uint112(-1) && _totalDistribution < uint112(-1) && block.number < uint32(-1), "OVERFLOW"); lastRewardBlock = uint32(block.number); diff --git a/contracts/SmartRoute/DODOV1Proxy02.sol b/contracts/SmartRoute/DODOV1Proxy02.sol index 4d52100..daadc81 100644 --- a/contracts/SmartRoute/DODOV1Proxy02.sol +++ b/contracts/SmartRoute/DODOV1Proxy02.sol @@ -18,7 +18,6 @@ import {IUni} from "./intf/IUni.sol"; import {IDODOApprove} from "../intf/IDODOApprove.sol"; import {IDODOV1Proxy02} from "./intf/IDODOV1Proxy02.sol"; import {InitializableOwnable} from "../lib/InitializableOwnable.sol"; -import {IDODOIncentive} from "./DODOIncentive.sol"; /** * @title DODOV1Proxy02 @@ -33,7 +32,6 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { // ============ Storage ============ address constant _ETH_ADDRESS_ = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public immutable _DODO_INCENTIVE_; address public immutable _DODO_APPROVE_; address public immutable _DODO_SELL_HELPER_; address public immutable _WETH_; @@ -63,14 +61,12 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { address dodoApporve, address dodoSellHelper, address weth, - address chiToken, - address dodoIncentive + address chiToken ) public { _DODO_APPROVE_ = dodoApporve; _DODO_SELL_HELPER_ = dodoSellHelper; _WETH_ = weth; _CHI_TOKEN_ = chiToken; - _DODO_INCENTIVE_ = dodoIncentive; } fallback() external payable {} @@ -97,7 +93,6 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, - bool isIncentive, uint256 deadLine ) external override payable judgeExpired(deadLine) returns (uint256 returnAmount) { require(dodoPairs.length > 0, "DODOV1Proxy02: PAIRS_EMPTY"); @@ -155,10 +150,6 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { if(gasleft() > 27710 + gasTokenBurn * 6080) IChi(_CHI_TOKEN_).freeUpTo(gasTokenBurn); } - - if(isIncentive) { - IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,toToken,msg.sender); - } } function externalSwap( @@ -169,11 +160,11 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { uint256 fromTokenAmount, uint256 minReturnAmount, bytes memory callDataConcat, - bool isIncentive, uint256 deadLine ) external override payable judgeExpired(deadLine) returns (uint256 returnAmount) { require(minReturnAmount > 0, "DODOV1Proxy02: RETURN_AMOUNT_ZERO"); - + require(fromToken != _CHI_TOKEN_, "DODOV1Proxy02: NOT_SUPPORT_SELL_CHI"); + address _fromToken = fromToken; address _toToken = toToken; @@ -208,10 +199,6 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { if(gasleft() > 27710 + _gasExternalReturn * 6080) IChi(_CHI_TOKEN_).freeUpTo(_gasExternalReturn); } - - if(isIncentive) { - IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(_fromToken,_toToken,msg.sender); - } } @@ -223,12 +210,12 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { address[] memory mixPairs, uint256[] memory directions, address[] memory portionPath, - bool isIncentive, uint256 deadLine ) external override payable judgeExpired(deadLine) returns (uint256 returnAmount) { require(mixPairs.length == directions.length, "DODOV1Proxy02: PARAMS_LENGTH_NOT_MATCH"); require(mixPairs.length > 0, "DODOV1Proxy02: PAIRS_EMPTY"); require(minReturnAmount > 0, "DODOV1Proxy02: RETURN_AMOUNT_ZERO"); + require(fromToken != _CHI_TOKEN_, "DODOV1Proxy02: NOT_SUPPORT_SELL_CHI"); uint256 toTokenOriginBalance = IERC20(toToken).universalBalanceOf(msg.sender); @@ -282,9 +269,5 @@ contract DODOV1Proxy02 is IDODOV1Proxy02, InitializableOwnable { if(gasleft() > 27710 + _gasExternalReturn * 6080) IChi(_CHI_TOKEN_).freeUpTo(_gasExternalReturn); } - - if(isIncentive) { - IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,toToken,msg.sender); - } } } diff --git a/contracts/SmartRoute/DODOV2Proxy01.sol b/contracts/SmartRoute/DODOV2Proxy01.sol index 8e00524..1c20e6f 100644 --- a/contracts/SmartRoute/DODOV2Proxy01.sol +++ b/contracts/SmartRoute/DODOV2Proxy01.sol @@ -15,14 +15,21 @@ import {IDODOSellHelper} from "./helper/DODOSellHelper.sol"; import {IERC20} from "../intf/IERC20.sol"; import {IWETH} from "../intf/IWETH.sol"; import {IUni} from "./intf/IUni.sol"; +import {IChi} from "./intf/IChi.sol"; import {SafeMath} from "../lib/SafeMath.sol"; import {UniversalERC20} from "./lib/UniversalERC20.sol"; import {SafeERC20} from "../lib/SafeERC20.sol"; import {DecimalMath} from "../lib/DecimalMath.sol"; import {ReentrancyGuard} from "../lib/ReentrancyGuard.sol"; import {InitializableOwnable} from "../lib/InitializableOwnable.sol"; +import {IDODOIncentive} from "./DODOIncentive.sol"; -//TODO: add gas return && trade incentive && replace DODOV1Proxy02 +/** + * @title DODOV2Proxy01 + * @author DODO Breeder + * + * @notice Entrance of trading in DODO platform + */ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable { using SafeMath for uint256; using UniversalERC20 for IERC20; @@ -36,6 +43,10 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable address public immutable _DVM_FACTORY_; address public immutable _DPP_FACTORY_; address public immutable _CP_FACTORY_; + address public immutable _DODO_INCENTIVE_; + address public immutable _CHI_TOKEN_; + uint256 public _GAS_DODO_MAX_RETURN_ = 0; + uint256 public _GAS_EXTERNAL_RETURN_ = 0; mapping (address => bool) public isWhiteListed; // ============ Events ============ @@ -65,7 +76,9 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable address cpFactory, address payable weth, address dodoApprove, - address dodoSellHelper + address dodoSellHelper, + address chiToken, + address dodoIncentive ) public { _DVM_FACTORY_ = dvmFactory; _DPP_FACTORY_ = dppFactory; @@ -73,6 +86,8 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable _WETH_ = weth; _DODO_APPROVE_ = dodoApprove; _DODO_SELL_HELPER_ = dodoSellHelper; + _CHI_TOKEN_ = chiToken; + _DODO_INCENTIVE_ = dodoIncentive; } function addWhiteList (address contractAddr) public onlyOwner { @@ -83,10 +98,14 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable isWhiteListed[contractAddr] = false; } + function updateGasReturn(uint256 newDodoGasReturn, uint256 newExternalGasReturn) public onlyOwner { + _GAS_DODO_MAX_RETURN_ = newDodoGasReturn; + _GAS_EXTERNAL_RETURN_ = newExternalGasReturn; + } + // ============ DVM Functions (create & add liquidity) ============ function createDODOVendingMachine( - address assetTo, address baseToken, address quoteToken, uint256 baseInAmount, @@ -134,12 +153,11 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable ); } - (shares, , ) = IDODOV2(newVendingMachine).buyShares(assetTo); + (shares, , ) = IDODOV2(newVendingMachine).buyShares(msg.sender); } function addDVMLiquidity( address dvmAddress, - address assetTo, uint256 baseInAmount, uint256 quoteInAmount, uint256 baseMinAmount, @@ -172,7 +190,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable _deposit(msg.sender, _dvm, IDODOV2(_dvm)._BASE_TOKEN_(), baseAdjustedInAmount, flag == 1); _deposit(msg.sender, _dvm, IDODOV2(_dvm)._QUOTE_TOKEN_(), quoteAdjustedInAmount, flag == 2); - (shares, , ) = IDODOV2(_dvm).buyShares(assetTo); + (shares, , ) = IDODOV2(_dvm).buyShares(msg.sender); // refund dust eth if (flag == 1 && msg.value > baseAdjustedInAmount) msg.sender.transfer(msg.value - baseAdjustedInAmount); if (flag == 2 && msg.value > quoteAdjustedInAmount) msg.sender.transfer(msg.value - quoteAdjustedInAmount); @@ -293,11 +311,11 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable // ============ Swap ============ function dodoSwapV2ETHToToken( - address payable assetTo, address toToken, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external @@ -308,6 +326,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable { require(dodoPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY"); require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO"); + uint256 originGas = gasleft(); uint256 originToTokenBalance = IERC20(toToken).balanceOf(msg.sender); IWETH(_WETH_).deposit{value: msg.value}(); @@ -316,9 +335,9 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable for (uint256 i = 0; i < dodoPairs.length; i++) { if (i == dodoPairs.length - 1) { if (directions & 1 == 0) { - IDODOV2(dodoPairs[i]).sellBase(assetTo); + IDODOV2(dodoPairs[i]).sellBase(msg.sender); } else { - IDODOV2(dodoPairs[i]).sellQuote(assetTo); + IDODOV2(dodoPairs[i]).sellQuote(msg.sender); } } else { if (directions & 1 == 0) { @@ -332,22 +351,29 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable returnAmount = IERC20(toToken).balanceOf(msg.sender).sub(originToTokenBalance); require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); + + _dodoGasReturn(originGas); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(_ETH_ADDRESS_,toToken,msg.sender); + } + emit OrderHistory( _ETH_ADDRESS_, toToken, - assetTo, + msg.sender, msg.value, returnAmount ); } function dodoSwapV2TokenToETH( - address payable assetTo, address fromToken, uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external @@ -357,6 +383,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable { require(dodoPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY"); require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO"); + uint256 originGas = gasleft(); IDODOApprove(_DODO_APPROVE_).claimTokens(fromToken, msg.sender, dodoPairs[0], fromTokenAmount); @@ -379,24 +406,31 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable returnAmount = IWETH(_WETH_).balanceOf(address(this)); require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); IWETH(_WETH_).withdraw(returnAmount); - assetTo.transfer(returnAmount); + msg.sender.transfer(returnAmount); + + _dodoGasReturn(originGas); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,_ETH_ADDRESS_,msg.sender); + } + emit OrderHistory( fromToken, _ETH_ADDRESS_, - assetTo, + msg.sender, fromTokenAmount, returnAmount ); } function dodoSwapV2TokenToToken( - address payable assetTo, address fromToken, address toToken, uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external @@ -406,6 +440,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable { require(dodoPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY"); require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO"); + uint256 originGas = gasleft(); uint256 originToTokenBalance = IERC20(toToken).balanceOf(msg.sender); IDODOApprove(_DODO_APPROVE_).claimTokens(fromToken, msg.sender, dodoPairs[0], fromTokenAmount); @@ -413,9 +448,9 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable for (uint256 i = 0; i < dodoPairs.length; i++) { if (i == dodoPairs.length - 1) { if (directions & 1 == 0) { - IDODOV2(dodoPairs[i]).sellBase(assetTo); + IDODOV2(dodoPairs[i]).sellBase(msg.sender); } else { - IDODOV2(dodoPairs[i]).sellQuote(assetTo); + IDODOV2(dodoPairs[i]).sellQuote(msg.sender); } } else { if (directions& 1 == 0) { @@ -428,10 +463,17 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable } returnAmount = IERC20(toToken).balanceOf(msg.sender).sub(originToTokenBalance); require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); + + _dodoGasReturn(originGas); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,toToken,msg.sender); + } + emit OrderHistory( fromToken, toToken, - assetTo, + msg.sender, fromTokenAmount, returnAmount ); @@ -445,6 +487,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable uint256 fromTokenAmount, uint256 minReturnAmount, bytes memory callDataConcat, + bool isIncentive, uint256 deadLine ) external @@ -479,6 +522,12 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable returnAmount = IERC20(toToken).universalBalanceOf(msg.sender).sub(toTokenOriginBalance); require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); + _externalGasReturn(); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(fromToken,toToken,msg.sender); + } + emit OrderHistory( fromToken, toToken, @@ -494,7 +543,8 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, - uint8[] memory directions, + uint256 directions, + bool isIncentive, uint256 deadLine ) external @@ -503,12 +553,18 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable judgeExpired(deadLine) returns (uint256 returnAmount) { - require(dodoPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH"); - _deposit(msg.sender, address(this), fromToken, fromTokenAmount, fromToken == _ETH_ADDRESS_); + require(dodoPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY"); + require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO"); + uint256 originGas = gasleft(); + + address _fromToken = fromToken; + address _toToken = toToken; + + _deposit(msg.sender, address(this), _fromToken, fromTokenAmount, _fromToken == _ETH_ADDRESS_); for (uint256 i = 0; i < dodoPairs.length; i++) { address curDodoPair = dodoPairs[i]; - if (directions[i] == 0) { + if (directions & 1 == 0) { address curDodoBase = IDODOV1(curDodoPair)._BASE_TOKEN_(); uint256 curAmountIn = IERC20(curDodoBase).balanceOf(address(this)); IERC20(curDodoBase).universalApproveMax(curDodoPair, curAmountIn); @@ -523,19 +579,27 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable ); IDODOV1(curDodoPair).buyBaseToken(canBuyBaseAmount, curAmountIn, ""); } + directions = directions >> 1; } + - if (toToken == _ETH_ADDRESS_) { + if (_toToken == _ETH_ADDRESS_) { returnAmount = IWETH(_WETH_).balanceOf(address(this)); IWETH(_WETH_).withdraw(returnAmount); } else { - returnAmount = IERC20(toToken).tokenBalanceOf(address(this)); + returnAmount = IERC20(_toToken).tokenBalanceOf(address(this)); } require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); - IERC20(toToken).universalTransfer(msg.sender, returnAmount); + IERC20(_toToken).universalTransfer(msg.sender, returnAmount); - emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount); + _dodoGasReturn(originGas); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(_fromToken,_toToken,msg.sender); + } + + emit OrderHistory(_fromToken, _toToken, msg.sender, fromTokenAmount, returnAmount); } function mixSwapV1( @@ -544,11 +608,15 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory mixPairs, - uint8[] memory directions, + uint256[] memory directions, address[] memory portionPath, + bool isIncentive, uint256 deadLine ) external override payable judgeExpired(deadLine) returns (uint256 returnAmount) { require(mixPairs.length == directions.length, "DODOV2Proxy01: PARAMS_LENGTH_NOT_MATCH"); + require(mixPairs.length > 0, "DODOV2Proxy01: PAIRS_EMPTY"); + require(minReturnAmount > 0, "DODOV2Proxy01: RETURN_AMOUNT_ZERO"); + uint256 toTokenOriginBalance = IERC20(toToken).universalBalanceOf(msg.sender); address _fromToken = fromToken; @@ -578,11 +646,6 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable } } - IERC20(_fromToken).universalTransfer( - msg.sender, - IERC20(_fromToken).universalBalanceOf(address(this)) - ); - IERC20(_toToken).universalTransfer( msg.sender, IERC20(_toToken).universalBalanceOf(address(this)) @@ -591,6 +654,11 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable returnAmount = IERC20(_toToken).universalBalanceOf(msg.sender).sub(toTokenOriginBalance); require(returnAmount >= minReturnAmount, "DODOV2Proxy01: Return amount is not enough"); + _externalGasReturn(); + + if(isIncentive) { + IDODOIncentive(_DODO_INCENTIVE_).triggerIncentive(_fromToken,_toToken,msg.sender); + } emit OrderHistory(_fromToken, _toToken, msg.sender, fromTokenAmount, returnAmount); } @@ -603,7 +671,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable uint256[] memory timeLine, uint256[] memory valueList, uint256 deadLine - ) external override payable judgeExpired(deadLine) returns (address payable newCrowdPooling) { + ) external override payable preventReentrant judgeExpired(deadLine) returns (address payable newCrowdPooling) { address _baseToken = baseToken; address _quoteToken = quoteToken == _ETH_ADDRESS_ ? _WETH_ : quoteToken; @@ -630,19 +698,17 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable } function bid( - address assetTo, address cpAddress, uint256 quoteAmount, uint8 flag, // 0 - ERC20, 1 - quoteInETH uint256 deadLine - ) external override payable judgeExpired(deadLine) { + ) external override payable preventReentrant judgeExpired(deadLine) { _deposit(msg.sender, cpAddress, IDODOV2(cpAddress)._QUOTE_TOKEN_(), quoteAmount, flag == 1); - IDODOV2(cpAddress).bid(assetTo); + IDODOV2(cpAddress).bid(msg.sender); } function addLiquidityToV1( - address assetTo, address pair, uint256 baseAmount, uint256 quoteAmount, @@ -650,7 +716,7 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable uint256 quoteMinShares, uint8 flag, // 0 erc20 In 1 baseInETH 2 quoteIn ETH uint256 deadLine - ) external override payable judgeExpired(deadLine) returns(uint256 baseShares, uint256 quoteShares) { + ) external override payable preventReentrant judgeExpired(deadLine) returns(uint256 baseShares, uint256 quoteShares) { address _baseToken = IDODOV1(pair)._BASE_TOKEN_(); address _quoteToken = IDODOV1(pair)._QUOTE_TOKEN_(); @@ -660,11 +726,11 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable if(baseAmount > 0) { IERC20(_baseToken).universalApproveMax(pair, baseAmount); - baseShares = IDODOV1(pair).depositBaseTo(assetTo, baseAmount); + baseShares = IDODOV1(pair).depositBaseTo(msg.sender, baseAmount); } if(quoteAmount > 0) { IERC20(_quoteToken).universalApproveMax(pair, quoteAmount); - quoteShares = IDODOV1(pair).depositQuoteTo(assetTo, quoteAmount); + quoteShares = IDODOV1(pair).depositQuoteTo(msg.sender, quoteAmount); } require(baseShares >= baseMinShares && quoteShares >= quoteMinShares,"DODOV2Proxy01: Return DLP is not enough"); @@ -703,4 +769,22 @@ contract DODOV2Proxy01 is IDODOV2Proxy01, ReentrancyGuard, InitializableOwnable SafeERC20.safeTransfer(IERC20(token), to, amount); } } + + function _dodoGasReturn(uint256 originGas) internal { + uint256 _gasDodoMaxReturn = _GAS_DODO_MAX_RETURN_; + if(_gasDodoMaxReturn > 0) { + uint256 calcGasTokenBurn = originGas.sub(gasleft()) / 65000; + uint256 gasTokenBurn = calcGasTokenBurn > _gasDodoMaxReturn ? _gasDodoMaxReturn : calcGasTokenBurn; + if(gasTokenBurn >= 3 && gasleft() > 27710 + gasTokenBurn * 6080) + IChi(_CHI_TOKEN_).freeUpTo(gasTokenBurn); + } + } + + function _externalGasReturn() internal { + uint256 _gasExternalReturn = _GAS_EXTERNAL_RETURN_; + if(_gasExternalReturn > 0) { + if(gasleft() > 27710 + _gasExternalReturn * 6080) + IChi(_CHI_TOKEN_).freeUpTo(_gasExternalReturn); + } + } } diff --git a/contracts/SmartRoute/helper/DODOCalleeHelper.sol b/contracts/SmartRoute/helper/DODOCalleeHelper.sol index caac55c..aa4827b 100644 --- a/contracts/SmartRoute/helper/DODOCalleeHelper.sol +++ b/contracts/SmartRoute/helper/DODOCalleeHelper.sol @@ -1,5 +1,5 @@ /* - + Copyright 2020 DODO ZOO. SPDX-License-Identifier: Apache-2.0 @@ -43,6 +43,27 @@ contract DODOCalleeHelper is ReentrancyGuard { _withdraw(assetTo, _quoteToken, quoteAmount, _quoteToken == _WETH_); } + function CPCancelCall( + address payable assetTo, + uint256 amount, + bytes calldata + )external preventReentrant{ + address _quoteToken = IDODOV2(msg.sender)._QUOTE_TOKEN_(); + _withdraw(assetTo, _quoteToken, amount, _quoteToken == _WETH_); + } + + function CPClaimBidCall( + address payable assetTo, + uint256 baseAmount, + uint256 quoteAmount, + bytes calldata + ) external preventReentrant { + address _baseToken = IDODOV2(msg.sender)._BASE_TOKEN_(); + address _quoteToken = IDODOV2(msg.sender)._QUOTE_TOKEN_(); + _withdraw(assetTo, _baseToken, baseAmount, _baseToken == _WETH_); + _withdraw(assetTo, _quoteToken, quoteAmount, _quoteToken == _WETH_); + } + function _withdraw( address payable to, address token, diff --git a/contracts/SmartRoute/helper/DODOSellHelper.sol b/contracts/SmartRoute/helper/DODOSellHelper.sol index f517f72..622de36 100644 --- a/contracts/SmartRoute/helper/DODOSellHelper.sol +++ b/contracts/SmartRoute/helper/DODOSellHelper.sol @@ -1,9 +1,3 @@ -/** - *Submitted for verification at Etherscan.io on 2020-10-10 - */ - -// File: contracts/intf/IDODO.sol - /* Copyright 2020 DODO ZOO. diff --git a/contracts/SmartRoute/intf/IDODOV1Proxy02.sol b/contracts/SmartRoute/intf/IDODOV1Proxy02.sol index 8e829a2..9052f64 100644 --- a/contracts/SmartRoute/intf/IDODOV1Proxy02.sol +++ b/contracts/SmartRoute/intf/IDODOV1Proxy02.sol @@ -16,7 +16,6 @@ interface IDODOV1Proxy02 { uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, - bool isIncentive, uint256 deadLine ) external payable returns (uint256 returnAmount); @@ -28,7 +27,6 @@ interface IDODOV1Proxy02 { uint256 fromTokenAmount, uint256 minReturnAmount, bytes memory callDataConcat, - bool isIncentive, uint256 deadLine ) external payable returns (uint256 returnAmount); @@ -40,7 +38,6 @@ interface IDODOV1Proxy02 { address[] memory mixPairs, uint256[] memory directions, address[] memory portionPath, - bool isIncentive, uint256 deadLine ) external payable returns (uint256 returnAmount); } diff --git a/contracts/SmartRoute/intf/IDODOV2Proxy01.sol b/contracts/SmartRoute/intf/IDODOV2Proxy01.sol index 51b93de..d37c9dc 100644 --- a/contracts/SmartRoute/intf/IDODOV2Proxy01.sol +++ b/contracts/SmartRoute/intf/IDODOV2Proxy01.sol @@ -8,41 +8,39 @@ pragma solidity 0.6.9; pragma experimental ABIEncoderV2; -import {IDODOV1Proxy01} from "./IDODOV1Proxy01.sol"; -interface IDODOV2Proxy01 is IDODOV1Proxy01 { +interface IDODOV2Proxy01 { function dodoSwapV2ETHToToken( - address payable assetTo, address toToken, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external payable returns (uint256 returnAmount); function dodoSwapV2TokenToETH( - address payable assetTo, address fromToken, uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external returns (uint256 returnAmount); function dodoSwapV2TokenToToken( - address payable assetTo, address fromToken, address toToken, uint256 fromTokenAmount, uint256 minReturnAmount, address[] memory dodoPairs, uint256 directions, + bool isIncentive, uint256 deadLine ) external returns (uint256 returnAmount); function createDODOVendingMachine( - address assetTo, address baseToken, address quoteToken, uint256 baseInAmount, @@ -55,7 +53,6 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 { function addDVMLiquidity( address dvmAddress, - address assetTo, uint256 baseInAmount, uint256 quoteInAmount, uint256 baseMinAmount, @@ -102,7 +99,6 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 { ) external payable returns (address payable newCrowdPooling); function bid( - address assetTo, address cpAddress, uint256 quoteAmount, uint8 flag, // 0 - ERC20, 1 - quoteInETH @@ -110,7 +106,6 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 { ) external payable; function addLiquidityToV1( - address to, address pair, uint256 baseAmount, uint256 quoteAmount, @@ -120,4 +115,39 @@ interface IDODOV2Proxy01 is IDODOV1Proxy01 { uint256 deadLine ) external payable returns(uint256, uint256); + function dodoSwapV1( + address fromToken, + address toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + address[] memory dodoPairs, + uint256 directions, + bool isIncentive, + uint256 deadLine + ) external payable returns (uint256 returnAmount); + + function externalSwap( + address fromToken, + address toToken, + address approveTarget, + address to, + uint256 fromTokenAmount, + uint256 minReturnAmount, + bytes memory callDataConcat, + bool isIncentive, + uint256 deadLine + ) external payable returns (uint256 returnAmount); + + function mixSwapV1( + address fromToken, + address toToken, + uint256 fromTokenAmount, + uint256 minReturnAmount, + address[] memory mixPairs, + uint256[] memory directions, + address[] memory portionPath, + bool isIncentive, + uint256 deadLine + ) external payable returns (uint256 returnAmount); + } diff --git a/contracts/intf/IDODOCallee.sol b/contracts/intf/IDODOCallee.sol index d506c0c..7118809 100644 --- a/contracts/intf/IDODOCallee.sol +++ b/contracts/intf/IDODOCallee.sol @@ -31,9 +31,16 @@ interface IDODOCallee { bytes calldata data ) external; - function CACancelCall( + function CPCancelCall( address sender, uint256 amount, bytes calldata data ) external; + + function CPClaimBidCall( + address sender, + uint256 baseAmount, + uint256 quoteAmount, + bytes calldata data + ) external; } diff --git a/contracts/lib/DODOMath.sol b/contracts/lib/DODOMath.sol index 249e211..fbd5c25 100644 --- a/contracts/lib/DODOMath.sol +++ b/contracts/lib/DODOMath.sol @@ -82,7 +82,7 @@ library DODOMath { } else if ((ki * delta) / ki == delta) { sqrt = (ki * delta).div(V1).add(DecimalMath.ONE2).sqrt(); } else { - sqrt = (4 * k).mul(i).div(V1).mul(delta).add(DecimalMath.ONE2).sqrt(); + sqrt = ki.div(V1).mul(delta).add(DecimalMath.ONE2).sqrt(); } uint256 premium = DecimalMath.divFloor(sqrt.sub(DecimalMath.ONE), k * 2).add(DecimalMath.ONE); diff --git a/deploy-detail-v2.0.txt b/deploy-detail-v2.0.txt index 44f81ca..3124c67 100644 --- a/deploy-detail-v2.0.txt +++ b/deploy-detail-v2.0.txt @@ -169,3 +169,23 @@ DODOApprove Address: 0xeEA9F08eBfde6915AB1C0051F3eB2612DbA95d5D DODOProxyV2 Address: 0x97B779AD504bbd5b1BFB50e57584a876Dc65171a Init DODOProxyV2 Tx: 0xd04c400fb46a0dd1e30ac04e9bce3e353869ffcb8ab7de622e2a936a3344d7b0 DODOApprove Init tx: 0xa78fe0b42e29489c1395e4574531902e1bc7348268bb102b001e4f3ffd47e83a +==================================================== +network type: kovan +Deploy time: 2021/1/8 下午8:28:05 +Deploy type: V2 +DvmTemplateAddress: 0xB13662Fcb9140dD573e74D76BACF2085A853C779 +DppTemplateAddress: 0x5121e563d6f091945244d02cfE68b1b617206d76 +DppAdminTemplateAddress: 0x59Fd9F2065b9aA717a51111c31B3cA89291BB866 +CpTemplateAddress: 0x7b10eE056D1FBeABd0174477418f90032807b06E +DODOApprove Address: 0xe51d8085aB43AC8BC98e965b2F7B79b998c23814 +DODOIncentiveAddress: 0xe7F4bd2a486DE815824335353973B2f4B94BaCeA +DODOIncentive Init tx: 0x7d1761b113f4e0760e42a6ef6c469cfc15e4635c389eef3add47801a0a9a52e6 +DvmFactoryAddress: 0x0ac46584e4566d5841E7D708Ab4D92Ef191fFe37 +Init DvmFactory Tx: 0x80fe93e8b765be77b07402c4d6569557080e30d8ca1dfaea030896f4365cbec7 +DppFactoryAddress: 0x6D4a70354cd03ae3A8461eDE9A4dAd445a169a6B +Init DppFactory Tx: 0x4befcdbc92ed3a6cab82e7c495085a346f0835eb27e943e2e1eb3ad600e79ee0 +CpFactoryAddress: 0x3a4Cdaf1796b985826CF1Ee451CACA991c2f79E1 +DODOProxyV2 Address: 0xB035847e685925647AaA8b9d74e3bFF36f81EBcB +Init DODOProxyV2 Tx: 0xe98f8e73c4ae138e8d9594dff37afd6657bb34ac8b644e1c6fa9c2f8df8413da +DODOApprove Init tx: 0x7b1718f215975439ff86791a0eb05cbea2081e5e1b9d9c6751280a24a1dbb17c +DODOIncentive ChangeProxy tx: 0x670e992a681a8808b112a8c5531df7ab11beac55f603d495a07ff91dce42cad4 diff --git a/kovan-mock-v2.0.txt b/kovan-mock-v2.0.txt index 44b0fa7..d3fac1d 100644 --- a/kovan-mock-v2.0.txt +++ b/kovan-mock-v2.0.txt @@ -255,3 +255,39 @@ Create DVM: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x5eca15b12d959dfcf9c71c5 Create DVM: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0xF2A7675f42F286214550c76c02D79efAd4A6D7ce Tx: 0xd6605ad6f00b8f01d2d0514e833dd1b559550cc9c61d90056930f9ca48d07f65 Create DPP: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0x50CA4A1714bE260B8aB8980c1649943b392d1cDf Tx: 0x8308da29d498548347380e73ad2daab06b4950db2d6e5e4766d858b4eea50eed Create DPP: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b Pool:0x2f487299a7f5aEe132348dC306b51816F4af17c2 Tx: 0x02fab2ac1c39494536d78004dd9de93e20609ea9a61f9aa9d1ddc1b0554071b2 +==================================================== +network type: kovan +Deploy time: 2021/1/8 上午9:29:18 +Mock TOKEN Tx: V2 +ERC20 address: 0xA22E0FdA630101d752C748DC213B36bE74A54cf7; Symbol:WOO0 +==================================================== +network type: kovan +Deploy time: 2021/1/8 上午9:37:13 +Mock POOL Tx: V2 +Approve:0xA22E0FdA630101d752C748DC213B36bE74A54cf7 Tx: 0xb1ad2f3b3782f3a09f75d951073ba7a1a07cde1696427f6383d8dcfcf471d0d6 +Approve:0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Tx: 0x11b190fa1dd1232a7ae8e17540c5af4c1b81ad0f20b5e19b28d410b84c8f02bb +Create DPP: 0xA22E0FdA630101d752C748DC213B36bE74A54cf7-0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Pool:0xCc50cC29769A296CB828496830664F747711F450 Tx: 0xf04ddff31fce21efe7f37a419ff15fb37e823abfe0cd2e44b47a52e0306879c1==================================================== +network type: kovan +Deploy time: 2021/1/8 下午7:59:15 +Mock TOKEN Tx: V2 +ERC20 address: 0xfF2985D13953Cb92ecc585aA2B6A4AF8cB46068f; Symbol:DODO +==================================================== +network type: kovan +Deploy time: 2021/1/8 下午8:38:40 +Mock POOL Tx: V2 +Approve:0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE Tx: 0xc3bef608ee3a68ae77fe7f1529d32d9780550b8c65a5d29ed00561e0248d2e48 +Approve:0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA Tx: 0x3fe5c3278d36a4fee5763e34d6c1ad19096252653535ed9b10128f7c63f29051 +Approve:0xFE1133ea03d701C5006b7f065bBf987955E7A67C Tx: 0x34c1fb0abe800f0b3b1619b878c3dd74556d8c3d6aca2bb470a2241568e210ad +Approve:0x123ee47BaE3F64d422F2FB18ac444B47c1880F4C Tx: 0xa4d65095bbad39f9d625d8ca38f7def63bbce089020b721a70af52d253f61d64 +Approve:0x0ab8EF8B19655F32959c83e5fC5cD6536065D28f Tx: 0x1cd9b9ffe78a589f864d8a433e2409e79d163042f22719f43d72b183a394944d +Approve:0x6462794c19e6b4543BEC56200212c7c746bbB9eB Tx: 0x8c0c314d652cf4527b38611f9c433756e509078c6491e81ae419aa5acdf8535c +Approve:0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Tx: 0x0090a4f02eebc8eab155bd94df6fd410d395fb8b83a537cd9970267a8f75fef9 +Approve:0x156595bAF85D5C29E91d959889B022d952190A64 Tx: 0x8f2570735caed9a65fde9971e657e6e1509335a4607ae576f97ad9f50ea47d69 +Create DVM: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Pool:0xA24A179a4Dfc1C9A1DbC2a17db5A9A79dC935d88 Tx: 0x5bfdb7dfb3b65fd77a10b95f1e0d4c8ea2ad8bc6432257bba5bf138ba439016f +Create DVM: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x156595bAF85D5C29E91d959889B022d952190A64 Pool:0x26115Cd3B06E2817E2Cb655199ccB58Ad4abdeDd Tx: 0xe9c558dbd3832936aa30fe588fad89a1b1e45d9f5e8241f44e765a76b7dcd670 +Create DVM: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Pool:0xf54d43c419754b9C397e5a69CAf418bdC55EfEd5 Tx: 0x8208048cb3d0346826b574851a78e25548f74ab13048830e190950cc548d7119 +Create DVM: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x156595bAF85D5C29E91d959889B022d952190A64 Pool:0xf5a379A1EfAa8bF60839D633547A3cCA311df89b Tx: 0x3080dfe6d54c3883547010781eca1276feb9cb3c0f0066cae12caff19b55e228 +Create DPP: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Pool:0xF00BEB2E974564B8867970FF8db7c0fFE0866c52 Tx: 0x214026df1fd2369c71d5050e6fa0060d3a55ec28f4d90f8696f2c4c517546914 +Create DPP: 0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE-0x156595bAF85D5C29E91d959889B022d952190A64 Pool:0x94648109F3DE33B2a04FbAE8Baf73F4Ea83ec259 Tx: 0xec487be5e60ad4614fa804c6798fe32ee5b87b6eb6b47f3d00435d220b8a9b84 +Create DPP: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b Pool:0x7e3261fEbD42a045429A7BfDF02307064034E157 Tx: 0x7412f7fbc70e236ffcd8a95193bfacc2926fc0dcfcc98cf0f507acb8489ece66 +Create DPP: 0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA-0x156595bAF85D5C29E91d959889B022d952190A64 Pool:0x875bCf57CC98e7c6cfC1F7c80ca0fb2709Bc4F01 Tx: 0x1fe29cf3ff586e914c81f31291912be69a7d73a50396f986ddf143495d8ba3ac diff --git a/migrations/3_deploy_v2.js b/migrations/3_deploy_v2.js index cf73313..f115de0 100644 --- a/migrations/3_deploy_v2.js +++ b/migrations/3_deploy_v2.js @@ -1,4 +1,5 @@ const fs = require("fs"); +const Web3 = require('web3'); const { deploySwitch } = require('../truffle-config.js') const file = fs.createWriteStream("../deploy-detail-v2.0.txt", { 'flags': 'a' }); let logger = new console.Console(file, file); @@ -9,6 +10,7 @@ const ConstFeeRateModelTemplate = artifacts.require("ConstFeeRateModel"); const PermissionManagerTemplate = artifacts.require("PermissionManager"); const ExternalValueTemplate = artifacts.require("ExternalValue"); +const ERC20Template = artifacts.require("InitializableERC20"); const DvmTemplate = artifacts.require("DVM"); const DppTemplate = artifacts.require("DPP"); const DppAdminTemplate = artifacts.require("DPPAdmin"); @@ -20,6 +22,7 @@ const CpFactory = artifacts.require("CrowdPoolingFactory"); const DODOApprove = artifacts.require("DODOApprove"); const DODOProxyV2 = artifacts.require("DODOV2Proxy01"); +const DODOIncentive = artifacts.require("DODOIncentive"); const DODOSellHelper = artifacts.require("DODOSellHelper"); const DODOCalleeHelper = artifacts.require("DODOCalleeHelper"); const DODOV2RouteHelper = artifacts.require("DODOV2RouteHelper"); @@ -53,6 +56,9 @@ module.exports = async (deployer, network, accounts) => { let CpFactoryAddress = ""; //Approve let DODOApproveAddress = ""; + //Incentive + let DODOIncentiveAddress = ""; + let DODOTokenAddress = ""; //Account let multiSigAddress = ""; let defaultMaintainer = ""; @@ -74,7 +80,7 @@ module.exports = async (deployer, network, accounts) => { // DefaultGasSourceAddress = "0xE0c0df0e0be7ec4f579503304a6C186cA4365407"; DefaultMtFeeRateAddress = "0xEfdE4225AC747136289979e29f1236527b2E4DB1"; DefaultPermissionAddress = "0xACc7E23368261e1E02103c4e5ae672E7D01f5797"; - + DvmTemplateAddress = ""; DppTemplateAddress = ""; DppAdminTemplateAddress = ""; @@ -85,6 +91,8 @@ module.exports = async (deployer, network, accounts) => { CpFactoryAddress = ""; //Approve DODOApproveAddress = ""; + DODOIncentiveAddress = ""; + DODOTokenAddress = "0xfF2985D13953Cb92ecc585aA2B6A4AF8cB46068f"; //Account multiSigAddress = accounts[0]; defaultMaintainer = accounts[0]; @@ -94,6 +102,7 @@ module.exports = async (deployer, network, accounts) => { WETHAddress = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; chiAddress = "0x0000000000004946c0e9F43F4Dee607b0eF1fA1c"; DODOCalleeHelperAddress = ""; + DODORouteV2HelperAddress = ""; //Template CloneFactoryAddress = ""; // FeeRateModelTemplateAddress = ""; @@ -115,6 +124,8 @@ module.exports = async (deployer, network, accounts) => { CpFactoryAddress = ""; //Proxy DODOApproveAddress = ""; + DODOIncentiveAddress = ""; + DODOTokenAddress = "0x43Dfc4159D86F3A37A5A4B3D4580b888ad7d4DDd"; //Account multiSigAddress = "0x95C4F5b83aA70810D4f142d58e5F7242Bd891CB0"; defaultMaintainer = "0x95C4F5b83aA70810D4f142d58e5F7242Bd891CB0"; @@ -124,6 +135,7 @@ module.exports = async (deployer, network, accounts) => { WETHAddress = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; chiAddress = "0x0000000000000000000000000000000000000000"; DODOCalleeHelperAddress = ""; + DODORouteV2HelperAddress = ""; //Template CloneFactoryAddress = ""; // FeeRateModelTemplateAddress = ""; @@ -145,28 +157,20 @@ module.exports = async (deployer, network, accounts) => { CpFactoryAddress = ""; //Proxy DODOApproveAddress = ""; + DODOIncentiveAddress = ""; + DODOTokenAddress = ""; //Account - multiSigAddress = ""; - defaultMaintainer = ""; + multiSigAddress = "0x4073f2b9bB95774531b9e23d206a308c614A943a"; + defaultMaintainer = "0x4073f2b9bB95774531b9e23d206a308c614A943a"; } else return; - - if(deploySwitch.HELPER_V2) { - logger.log("===================================================="); - logger.log("network type: " + network); - logger.log("Deploy time: " + new Date().toLocaleString()); - logger.log("Deploy type: HELPER V2"); - - await deployer.deploy(DODOV2RouteHelper, "0xF2a62693FB14b326C3719e5aeEF28e8e66dC954e","0x58Bc8D248AcbE95CE29CF893C6666D58AF92d941"); - DODOV2RouteHelperAddress = DODOV2RouteHelper.address; - logger.log("DODOV2RouteHelper Address: ", DODOV2RouteHelperAddress); - } - if (deploySwitch.DEPLOY_V2) { logger.log("===================================================="); logger.log("network type: " + network); logger.log("Deploy time: " + new Date().toLocaleString()); logger.log("Deploy type: V2"); + if (DODOTokenAddress == "") return; + //Helper if (DODOSellHelperAddress == "") { await deployer.deploy(DODOSellHelper); @@ -262,6 +266,16 @@ module.exports = async (deployer, network, accounts) => { logger.log("DODOApprove Address: ", DODOApproveAddress); } + //Incentive + if (DODOIncentiveAddress == "") { + await deployer.deploy(DODOIncentive, DODOTokenAddress); + DODOIncentiveAddress = DODOIncentive.address; + logger.log("DODOIncentiveAddress: ", DODOIncentiveAddress); + const DODOIncentiveInstance = await DODOIncentive.at(DODOIncentiveAddress); + var tx = await DODOIncentiveInstance.initOwner(multiSigAddress); + logger.log("DODOIncentive Init tx: ", tx.tx); + } + //Factory if (DvmFactoryAddress == "") { await deployer.deploy( @@ -294,7 +308,7 @@ module.exports = async (deployer, network, accounts) => { var tx = await DppFactoryInstance.initOwner(multiSigAddress); logger.log("Init DppFactory Tx:", tx.tx); } - + if (CpFactoryAddress == "") { await deployer.deploy( CpFactory, @@ -323,16 +337,41 @@ module.exports = async (deployer, network, accounts) => { CpFactoryAddress, WETHAddress, DODOApproveAddress, - DODOSellHelperAddress + DODOSellHelperAddress, + chiAddress, + DODOIncentiveAddress ); logger.log("DODOProxyV2 Address: ", DODOProxyV2.address); const DODOProxyV2Instance = await DODOProxyV2.at(DODOProxyV2.address); var tx = await DODOProxyV2Instance.initOwner(multiSigAddress); logger.log("Init DODOProxyV2 Tx:", tx.tx); - + const DODOApproveInstance = await DODOApprove.at(DODOApproveAddress); - var tx = await DODOApproveInstance.init(multiSigAddress,DODOProxyV2.address); + var tx = await DODOApproveInstance.init(multiSigAddress, DODOProxyV2.address); logger.log("DODOApprove Init tx: ", tx.tx); + + + if (network == 'kovan') { + //1. Proxy whiteList + + //2. ChangeDODO Incentive proxy + const DODOIncentiveInstance = await DODOIncentive.at(DODOIncentiveAddress); + var tx = await DODOIncentiveInstance.changeDODOProxy(DODOProxyV2.address); + logger.log("DODOIncentive ChangeProxy tx: ", tx.tx); + + //3. Open trade incentive + // const provider = new Web3.providers.HttpProvider("https://kovan.infura.io/v3/22d4a3b2df0e47b78d458f43fe50a199"); + // if (!provider) { + // throw new Error(`Unable to find provider for network: ${network}`) + // } + // const web3 = new Web3(provider) + // const blockNum = await web3.eth.getBlockNumber(); + // var tx = await DODOIncentiveInstance.switchIncentive(blockNum + 1); + // logger.log("DODOIncentive OpenSwitch tx: ", tx.tx); + + //4. Transfer DODO to Trade Incentive + } + } }; diff --git a/migrations/4_deploy_v2_mock.js b/migrations/4_deploy_v2_mock.js index e619d35..25beb44 100644 --- a/migrations/4_deploy_v2_mock.js +++ b/migrations/4_deploy_v2_mock.js @@ -13,54 +13,48 @@ 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: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH + quoteAddr: "0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b", //USDC + lpFeeRate: "0", //0 + i: "10000000", //10 + k: "500000000000000000" //0.5 + }, + { + baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0 + quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT lpFeeRate: "3000000000000000", //0.003 - mtFeeRate: "1000000000000000", //0.001 - i: "45000000000000000000", //45 - k: "800000000000000000" //0.8 + i: "10000000", //10 + k: "0" //0 }, { baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1 - quoteAddr: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH - lpFeeRate: "3000000000000000", //0.003 - mtFeeRate: "1000000000000000", //0.001 - i: "30000000000000000000", //30 - k: "300000000000000000" //0.3 + quoteAddr: "0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b", //USDC + lpFeeRate: "0", //0 + i: "5000000", //5 + k: "1000000000000000000" //1 }, + { + baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1 + quoteAddr: "0x156595bAF85D5C29E91d959889B022d952190A64", //USDT + lpFeeRate: "3000000000000000", //0.003 + i: "8000000", //8 + k: "900000000000000000" //0.9 + }, + // { + // baseAddr: "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", //ABC0 + // quoteAddr: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH + // lpFeeRate: "3000000000000000", //0.003 + // i: "45000000000000000000", //45 + // k: "800000000000000000" //0.8 + // }, + // { + // baseAddr: "0xd7f02D1b4F9495B549787808503Ecfd231C3fbDA", //ABC1 + // quoteAddr: "0x5eca15b12d959dfcf9c71c59f8b467eb8c6efd0b", //WETH + // lpFeeRate: "0", //0.003 + // i: "30000000000000000000", //30 + // k: "300000000000000000" //0.3 + // }, ]; module.exports = async (deployer, network, accounts) => { @@ -70,10 +64,10 @@ module.exports = async (deployer, network, accounts) => { let MintableERC20TemplateAddress = "0xA45a64DAba80757432fA4d654Df12f65f020C13C"; let ERC20FactoryAddress = "0xCb1A2f64EfB02803276BFB5a8D511C4D950282a0"; - let DPPFactoryAddress = "0x58Bc8D248AcbE95CE29CF893C6666D58AF92d941"; - let DVMFactoryAddress = "0xF2a62693FB14b326C3719e5aeEF28e8e66dC954e"; - let DODOApproveAddress = "0xeEA9F08eBfde6915AB1C0051F3eB2612DbA95d5D"; - let DODOProxyV2Address = "0x97B779AD504bbd5b1BFB50e57584a876Dc65171a"; + let DPPFactoryAddress = "0x6D4a70354cd03ae3A8461eDE9A4dAd445a169a6B"; + let DVMFactoryAddress = "0x0ac46584e4566d5841E7D708Ab4D92Ef191fFe37"; + let DODOApproveAddress = "0xe51d8085aB43AC8BC98e965b2F7B79b998c23814"; + let DODOProxyV2Address = "0xB035847e685925647AaA8b9d74e3bFF36f81EBcB"; const provider = new Web3.providers.HttpProvider("https://kovan.infura.io/v3/22d4a3b2df0e47b78d458f43fe50a199"); @@ -104,7 +98,7 @@ module.exports = async (deployer, network, accounts) => { const DODOProxyV2Instance = await DODOProxyV2.at(DODOProxyV2Address); var tx = await DODOProxyV2Instance.dodoSwapV2TokenToToken( accounts[0], - "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e", + "0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b", "0xd8C30a4E866B188F16aD266dC3333BD47F34ebaE", web3.utils.toWei("10", 'mwei'), 0, @@ -125,7 +119,7 @@ module.exports = async (deployer, network, accounts) => { const token3Addr = "0x123ee47BaE3F64d422F2FB18ac444B47c1880F4C"; const token4Addr = "0x0ab8EF8B19655F32959c83e5fC5cD6536065D28f"; const token5Addr = "0x6462794c19e6b4543BEC56200212c7c746bbB9eB"; - const quote0Addr = "0x69c8a7fc6e05d7aa36114b3e35f62deca8e11f6e"; + const quote0Addr = "0x43688f367eb83697c3ca5d03c5055b6bd6f6ac4b"; const quote1Addr = "0x156595bAF85D5C29E91d959889B022d952190A64"; const token0 = await ERC20Template.at(token0Addr); const token1 = await ERC20Template.at(token1Addr); @@ -158,14 +152,13 @@ module.exports = async (deployer, network, accounts) => { const DPPFactoryInstance = await DPPFactory.at(DPPFactoryAddress); const assetTo = accounts[0]; - const baseInAmount = web3.utils.toWei("1000", 'ether'); - // const quoteInAmount = web3.utils.toWei("100", 'mwei'); - const quoteInAmount = web3.utils.toWei("0", 'ether'); + const baseInAmount = web3.utils.toWei("100000", 'ether'); + const quoteInAmount = web3.utils.toWei("10000", '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++) { tx = await DODOProxyV2Instance.createDODOVendingMachine( - assetTo, POOL_PARAM[i].baseAddr, POOL_PARAM[i].quoteAddr, baseInAmount, @@ -226,11 +219,11 @@ module.exports = async (deployer, network, accounts) => { const ERC20FactoryInstance = await ERC20Factory.at(ERC20FactoryAddress); - const totalSupply = web3.utils.toWei("100000000", 'mwei'); - for (let i = 0; i < 8; i++) { - var tx = await ERC20FactoryInstance.createStdERC20(totalSupply, 'ABC Token', 'ABC' + i, 18); + const totalSupply = web3.utils.toWei("1000000000", 'ether'); + for (let i = 0; i < 1; i++) { + var tx = await ERC20FactoryInstance.createStdERC20(totalSupply, 'DODO Bird', 'DODO', 18); // var tx = await ERC20FactoryInstance.createStdERC20(totalSupply, 'USDT Token', 'USDT', 6); - logger.log("ERC20 address: ", tx.logs[0].args['erc20'] + "; Symbol:" + 'ABC' + i); + logger.log("ERC20 address: ", tx.logs[0].args['erc20'] + "; Symbol:" + 'DODO'); // logger.log("ERC20 address: ", tx.logs[0].args['erc20'] + "; Symbol:" + 'USDT'); } } diff --git a/test/CrowdPooling/CPBid.test.ts b/test/CrowdPooling/CPBid.test.ts index 252c837..cd88944 100644 --- a/test/CrowdPooling/CPBid.test.ts +++ b/test/CrowdPooling/CPBid.test.ts @@ -41,6 +41,7 @@ describe("Funding", () => { freezeDuration: new BigNumber(86400), vestingDuration: new BigNumber(86400), cliffRate: decimalStr("1"), + quoteTokenContract:"" } ctx = new CPContext(); await ctx.init(config); @@ -57,7 +58,7 @@ describe("Funding", () => { describe("bid & cancel", () => { - it("bid", async () => { + it("bid and cancel", async () => { await ctx.QUOTE.methods.transfer(ctx.CP.options.address, decimalStr("100")).send(ctx.sendParam(bidder1)) await logGas(ctx.CP.methods.bid(bidder1), ctx.sendParam(bidder1), "bid") assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("99.9")) @@ -71,10 +72,11 @@ describe("Funding", () => { assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), decimalStr("0.15")) await ctx.EVM.increaseTime(86400) - await logGas(ctx.CP.methods.cancel(bidder1, decimalStr("20")), ctx.sendParam(bidder1), "cancel") + await logGas(ctx.CP.methods.cancel(bidder1, decimalStr("20"),"0x"), ctx.sendParam(bidder1), "cancel") assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("79.9")) assert.equal(await ctx.CP.methods._TOTAL_SHARES_().call(), decimalStr("129.85")) assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("920")) + }) }) diff --git a/test/CrowdPooling/CPCancelEthBid.test.ts b/test/CrowdPooling/CPCancelEthBid.test.ts new file mode 100644 index 0000000..da07bd5 --- /dev/null +++ b/test/CrowdPooling/CPCancelEthBid.test.ts @@ -0,0 +1,118 @@ +/* + + 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 { CPContext, CPContextInitConfig } from '../utils/CrowdPoolingContext'; +import BigNumber from 'bignumber.js'; +import { assert } from 'chai'; +const truffleAssert = require('truffle-assertions'); + +let bidder1: string; +let bidder2: string; +let config: CPContextInitConfig + +async function init(ctx: CPContext): Promise { + bidder1 = ctx.SpareAccounts[1] + bidder2 = ctx.SpareAccounts[2] + await ctx.QUOTE.methods.deposit().send(ctx.sendParam(bidder1,"0.1")) + await ctx.QUOTE.methods.deposit().send(ctx.sendParam(bidder2,"0.5")) +} + +describe("Funding", () => { + let snapshotId: string; + let ctx: CPContext; + + before(async () => { + config = { + totalBase: decimalStr("0.1"), + poolQuoteCap: decimalStr("0.5"), + k: decimalStr("0"), + i: decimalStr("10"), + lpFeeRate: decimalStr("0.002"), + bidDuration: new BigNumber(86400), + calmDuration: new BigNumber(86400), + freezeDuration: new BigNumber(86400), + vestingDuration: new BigNumber(86400), + cliffRate: decimalStr("1"), + quoteTokenContract:"WETH9" + } + ctx = new CPContext(); + await ctx.init(config); + await init(ctx); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("eth bid & cancel", () => { + + it("cancel by callee contract", async () => { + await ctx.QUOTE.methods.transfer(ctx.CP.options.address, decimalStr("0.1")).send(ctx.sendParam(bidder1)) + await logGas(ctx.CP.methods.bid(bidder1), ctx.sendParam(bidder1), "bidder1 bid") + assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("0.0999")) + assert.equal(await ctx.CP.methods._TOTAL_SHARES_().call(), decimalStr("0.0999")) + assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), decimalStr("0.0001")) + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("0")) + + await logGas(ctx.CP.methods.cancel(bidder1, decimalStr("0.05"),"0x"), ctx.sendParam(bidder1), "cancel and get 0.05 weth") + assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("0.0499")) + assert.equal(await ctx.CP.methods._TOTAL_SHARES_().call(), decimalStr("0.0499")) + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("0.05")) + + let beforeEthBalance = await ctx.Web3.eth.getBalance(bidder1); + let receipt = await logGas(ctx.CP.methods.cancel(ctx.DODOCallee.options.address, decimalStr("0.02"),"0x00"), ctx.sendParam(bidder1), "cancel and get 0.02 eth") + assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("0.0299")) + assert.equal(await ctx.CP.methods._TOTAL_SHARES_().call(), decimalStr("0.0299")) + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("0.05")) + let afterEthBalance = await ctx.Web3.eth.getBalance(bidder1); + assert.equal(Number.parseInt(receipt["events"]["1"]["raw"]["data"],16),Number(decimalStr("0.02"))); + // assert.equal(Number(afterEthBalance) - Number(beforeEthBalance) + Number(receipt.gasUsed)*Number(mweiStr("1000")),Number(decimalStr("0.02"))); + + }) + + it("claim by callee contract", async () => { + await ctx.QUOTE.methods.deposit().send(ctx.sendParam(bidder1,"0.4")) + await ctx.QUOTE.methods.deposit().send(ctx.sendParam(bidder2,"0.5")) + + await ctx.QUOTE.methods.transfer(ctx.CP.options.address, decimalStr("0.5")).send(ctx.sendParam(bidder1)) + await logGas(ctx.CP.methods.bid(bidder1), ctx.sendParam(bidder1), "bidder1 bid") + await ctx.QUOTE.methods.transfer(ctx.CP.options.address, decimalStr("0.5")).send(ctx.sendParam(bidder2)) + await logGas(ctx.CP.methods.bid(bidder2), ctx.sendParam(bidder2), "bidder2 bid") + + assert.equal(await ctx.CP.methods.getShares(bidder1).call(), decimalStr("0.4995")) + assert.equal(await ctx.CP.methods.getShares(bidder2).call(), decimalStr("0.4995")) + assert.equal(await ctx.CP.methods._TOTAL_SHARES_().call(), decimalStr("0.999")) + assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), decimalStr("0.999")) + assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), decimalStr("0.001")) + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("0")) + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), decimalStr("0.5")) + + await ctx.EVM.increaseTime(86400 *2) + await logGas(ctx.CP.methods.settle(), ctx.sendParam(ctx.Deployer), "settle") + assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), decimalStr("0.499")) + + await ctx.EVM.increaseTime(86400 * 2) + assert.equal(await ctx.BASE.methods.balanceOf(bidder1).call(), "0") + let receipt1 = await logGas(await ctx.CP.methods.bidderClaim(bidder1,"0x"),ctx.sendParam(bidder1),"claim"); + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), decimalStr("0.2495")) + + let receipt2 = await logGas(await ctx.CP.methods.bidderClaim(ctx.DODOCallee.options.address,"0x00"),ctx.sendParam(bidder2),"claim"); + assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), decimalStr("0.5")) + assert.equal(Number.parseInt(receipt2["events"]["3"]["raw"]["data"],16),Number(decimalStr("0.2495"))); + + }) + + }) +}) diff --git a/test/CrowdPooling/CPSettle.test.ts b/test/CrowdPooling/CPSettle.test.ts index 8884afe..5408676 100644 --- a/test/CrowdPooling/CPSettle.test.ts +++ b/test/CrowdPooling/CPSettle.test.ts @@ -40,6 +40,7 @@ describe("Funding", () => { freezeDuration: new BigNumber(86400), vestingDuration: new BigNumber(86400), cliffRate: decimalStr("1"), + quoteTokenContract:'' } ctx = new CPContext(); await ctx.init(config); diff --git a/test/CrowdPooling/CPSettleReversePool.test.ts b/test/CrowdPooling/CPSettleReversePool.test.ts index ce63c09..bb3f845 100644 --- a/test/CrowdPooling/CPSettleReversePool.test.ts +++ b/test/CrowdPooling/CPSettleReversePool.test.ts @@ -41,6 +41,7 @@ describe("Funding", () => { freezeDuration: new BigNumber(86400), vestingDuration: new BigNumber(86400), cliffRate: decimalStr("1"), + quoteTokenContract:'' } ctx = new CPContext(); await ctx.init(config); diff --git a/test/CrowdPooling/CPVesting.test.ts b/test/CrowdPooling/CPVesting.test.ts index 690bc8b..507a3f1 100644 --- a/test/CrowdPooling/CPVesting.test.ts +++ b/test/CrowdPooling/CPVesting.test.ts @@ -39,6 +39,7 @@ describe("Funding", () => { freezeDuration: new BigNumber(86400), vestingDuration: new BigNumber(86400), cliffRate: decimalStr("1"), + quoteTokenContract:'' } ctx = new CPContext(); await ctx.init(config); @@ -69,11 +70,11 @@ describe("Funding", () => { assert.equal(await ctx.BASE.methods.balanceOf(ctx.CP.options.address).call(), "2997000000000000000000") assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), "0") - await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder1)) + await ctx.CP.methods.bidderClaim(bidder1, "0x").send(ctx.sendParam(bidder1)) assert.equal(await ctx.BASE.methods.balanceOf(bidder1).call(), "999000000000000000000") assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), "0") - await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder2)) + await ctx.CP.methods.bidderClaim(bidder2, "0x").send(ctx.sendParam(bidder2)) assert.equal(await ctx.BASE.methods.balanceOf(bidder2).call(), "1998000000000000000000") assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), "0") @@ -92,11 +93,11 @@ describe("Funding", () => { assert.equal(await ctx.BASE.methods.balanceOf(ctx.CP.options.address).call(), "5000000000000000000000") assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.CP.options.address).call(), decimalStr("39910")) - await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder1)) + await ctx.CP.methods.bidderClaim(bidder1, "0x").send(ctx.sendParam(bidder1)) assert.equal(await ctx.BASE.methods.balanceOf(bidder1).call(), "1666666666666666666666") assert.equal(await ctx.QUOTE.methods.balanceOf(bidder1).call(), "13303333333333333333333") - await ctx.CP.methods.bidderClaim().send(ctx.sendParam(bidder2)) + await ctx.CP.methods.bidderClaim(bidder2, "0x").send(ctx.sendParam(bidder2)) assert.equal(await ctx.BASE.methods.balanceOf(bidder2).call(), "3333333333333333333333") assert.equal(await ctx.QUOTE.methods.balanceOf(bidder2).call(), "26606666666666666666666") }) diff --git a/test/DVM/trader.test.ts b/test/DVM/trader.test.ts index ba89631..3090cee 100644 --- a/test/DVM/trader.test.ts +++ b/test/DVM/trader.test.ts @@ -163,51 +163,69 @@ describe("Trader", () => { }); it("flash loan", async () => { - // buy + // console.log(await ctx.DVM.methods.getVaultReserve().call()) + // console.log(await ctx.DVM.methods.getQuoteInput().call()) + // // buy await ctx.transferQuoteToDVM(trader, decimalStr("200")) + // await ctx.DVM.methods.sync().send(ctx.sendParam(ctx.Deployer)) + // console.log(await ctx.DVM.methods.getVaultReserve().call()) + + // console.log(await ctx.DVM.methods.getBaseInput().call()) + // console.log(await ctx.DVM.methods.getQuoteInput().call()) + // console.log(await ctx.DVM.methods.getVaultReserve().call()) + + + // 1950668837297593488 + // 1946763594380080790 + + // var quoteInput = await ctx.DVM.methods.getQuoteInput().call() + // console.log(await ctx.DVM.methods.querySellQuote(ctx.Deployer, quoteInput).call()) // buy failed - await truffleAssert.reverts(ctx.DVM.methods.flashLoan("1946763594380080790", "0", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED") + await truffleAssert.reverts(ctx.DVM.methods.flashLoan("1950668837297593489", "0", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED") // buy succeed - await ctx.DVM.methods.flashLoan("1946763594380080789", "0", trader, "0x").send(ctx.sendParam(trader)) + await ctx.DVM.methods.flashLoan("1950668837297593488", "0", trader, "0x").send(ctx.sendParam(trader)) // trader balances assert.equal( await ctx.BASE.methods.balanceOf(trader).call(), - "11946763594380080789" + "11950668837297593488" ); // sell await ctx.transferBaseToDVM(trader, decimalStr("1")) + // var baseInput = await ctx.DVM.methods.getBaseInput().call() + // console.log(await ctx.DVM.methods.querySellBase(ctx.Deployer, baseInput).call()) + + // sell failed - await truffleAssert.reverts(ctx.DVM.methods.flashLoan("0", "103421810640399874606", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED") + await truffleAssert.reverts(ctx.DVM.methods.flashLoan("0", "103631079987679211408", trader, "0x").send(ctx.sendParam(trader)), "FLASH_LOAN_FAILED") // sell succeed - await ctx.DVM.methods.flashLoan("0", "103421810640399874605", trader, "0x").send(ctx.sendParam(trader)) + await ctx.DVM.methods.flashLoan("0", "103631079987679211407", trader, "0x").send(ctx.sendParam(trader)) // trader balances assert.equal( await ctx.QUOTE.methods.balanceOf(trader).call(), - "903421810640399874605" + "903631079987679211407" ); }) it("revert cases", async () => { - // var gasPriceLimitContract = getContractWithAddress(EXTERNAL_VALUE_NAME, await ctx.DVM.methods._GAS_PRICE_LIMIT_().call()) - // await gasPriceLimitContract.methods.set(gweiStr("10")).send(ctx.sendParam(ctx.Deployer)) - - await truffleAssert.reverts( - ctx.DVM.methods.sellQuote(trader).send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), "GAS_PRICE_EXCEED" - ) - - await ctx.transferBaseToDVM(trader, decimalStr("1")) + await ctx.transferBaseToDVM(trader, decimalStr("10")) await truffleAssert.reverts( ctx.DVM.methods.sellBase(trader).send(ctx.sendParam(trader)), "TARGET_IS_ZERO" ) + + // var gasPriceLimitContract = getContractWithAddress(EXTERNAL_VALUE_NAME, await ctx.DVM.methods._GAS_PRICE_LIMIT_().call()) + // await gasPriceLimitContract.methods.set(gweiStr("10")).send(ctx.sendParam(ctx.Deployer)) + // await truffleAssert.reverts( + // ctx.DVM.methods.sellQuote(trader).send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), "GAS_PRICE_EXCEED" + // ) }) it("sync", async () => { @@ -215,7 +233,7 @@ describe("Trader", () => { await ctx.QUOTE.methods.mint(ctx.DVM.options.address, decimalStr("456")).send(ctx.sendParam(ctx.Deployer)) await ctx.DVM.methods.sync().send(ctx.sendParam(ctx.Deployer)) - assert.equal(await ctx.DVM.methods._BASE_RESERVE_().call(), decimalStr("123")) + assert.equal(await ctx.DVM.methods._BASE_RESERVE_().call(), decimalStr("133"))//after init base is 10,so current should be 10+123=133 assert.equal(await ctx.DVM.methods._QUOTE_RESERVE_().call(), decimalStr("456")) }) }); diff --git a/test/Route/Incentive.test.ts b/test/Route/Incentive.test.ts deleted file mode 100644 index 8e05f0c..0000000 --- a/test/Route/Incentive.test.ts +++ /dev/null @@ -1,274 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import BigNumber from 'bignumber.js'; -import { DODOContext, getDODOContext } from '../utils-v1/ProxyContextV1'; -import { decimalStr, MAX_UINT256, fromWei, mweiStr } from '../utils-v1/Converter'; -import { logGas } from '../utils-v1/Log'; -import * as contracts from '../utils-v1/Contracts'; -import { assert } from 'chai'; - -let lp: string; -let trader: string; - -async function initDODO_USDT(ctx: DODOContext): Promise { - await ctx.setOraclePrice(ctx.DODO_USDT_ORACLE, mweiStr("0.1")); - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - - let DODO = ctx.DODO; - let USDT = ctx.USDT; - let DODO_USDT = ctx.DODO_USDT; - await ctx.approvePair(DODO, USDT, DODO_USDT.options.address, lp); - await ctx.approvePair(DODO, USDT, DODO_USDT.options.address, trader); - - await ctx.mintToken(DODO, USDT, lp, decimalStr("10000000"), mweiStr("1000000")); - - await DODO_USDT.methods - .depositBaseTo(lp, decimalStr("10000000")) - .send(ctx.sendParam(lp)); - await DODO_USDT.methods - .depositQuoteTo(lp, mweiStr("1000000")) - .send(ctx.sendParam(lp)); -} - -async function initUSDT_USDC(ctx: DODOContext): Promise { - await ctx.setOraclePrice(ctx.USDT_USDC_ORACLE, decimalStr("1")); - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - - let USDT = ctx.USDT; - let USDC = ctx.USDC; - let USDT_USDC = ctx.USDT_USDC; - - await ctx.approvePair(USDT, USDC, USDT_USDC.options.address, lp); - await ctx.mintToken(USDT, USDC, lp, mweiStr("1000000"), mweiStr("1000000")); - - await USDT_USDC.methods - .depositBaseTo(lp, mweiStr("1000000")) - .send(ctx.sendParam(lp)); - await USDT_USDC.methods - .depositQuoteTo(lp, mweiStr("1000000")) - .send(ctx.sendParam(lp)); -} - - -async function initWETH_USDC(ctx: DODOContext): Promise { - await ctx.setOraclePrice(ctx.WETH_USDC_ORACLE, mweiStr("450")); - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - - let WETH = ctx.WETH; - let USDC = ctx.USDC; - let WETH_USDC = ctx.WETH_USDC; - - await ctx.approvePair(WETH, USDC, WETH_USDC.options.address, lp); - await ctx.mintToken(null, USDC, lp, decimalStr("0"), mweiStr("3600")); - await WETH.methods.deposit().send(ctx.sendParam(lp, '8')); - - await WETH_USDC.methods - .depositBaseTo(lp, decimalStr("8")) - .send(ctx.sendParam(lp)); - await WETH_USDC.methods - .depositQuoteTo(lp, mweiStr("3600")) - .send(ctx.sendParam(lp)); -} - -async function initIncentive(ctx: DODOContext): Promise { - var blockNum = await ctx.Web3.eth.getBlockNumber(); - await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer)); - await ctx.mintToken(ctx.DODO, null, ctx.DODOIncentive.options.address, decimalStr("10000"), mweiStr("0")); -} - -//mock sdk logic -async function calcRoute(ctx: DODOContext, fromTokenAmount: string, slippage: number, routes: any[], pairs: any[], isIncentive: boolean) { - let tmpDirections: number[] = [] - let strDirections: string = '' - let dodoPairs: string[] = [] - - for (let i = 0; i < pairs.length; i++) { - let curPair = pairs[i] - dodoPairs.push(curPair.pair) - if (routes[i].address == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') { - tmpDirections[i] = 0; - } else if (curPair.base === routes[i].address) { - tmpDirections[i] = 0; - } else { - tmpDirections[i] = 1; - } - } - - var [returmAmount,] = await ctx.DODOSwapCalcHelper.methods.calcReturnAmountV1( - fromTokenAmount, - dodoPairs, - tmpDirections, - ).call(); - // console.log("returnAmount:", returmAmount) - // console.log("localAmount:", swapAmount) - // console.log("midPrices:", midPrices) - - - let toAmount = new BigNumber(returmAmount).multipliedBy(1 - slippage).toFixed(0, BigNumber.ROUND_DOWN) - let deadline = Math.floor(new Date().getTime() / 1000 + 60 * 10); - - for (let i = tmpDirections.length - 1; i >= 0; i--) { - strDirections += tmpDirections[i].toString() - } - - return ctx.DODOV1Proxy02.methods.dodoSwapV1( - routes[0].address, - routes[routes.length - 1].address, - fromTokenAmount, - toAmount, - dodoPairs, - parseInt(strDirections, 2), - isIncentive, - deadline - ) -} - -describe("Trader", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - let ETH = await contracts.newContract( - contracts.WETH_CONTRACT_NAME - ); - ctx = await getDODOContext(ETH.options.address); - await initDODO_USDT(ctx); - await initUSDT_USDC(ctx); - await initWETH_USDC(ctx); - await initIncentive(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("route calc with incentive test", () => { - it("incentive-switch with trade", async () => { - await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); - var totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - var blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("Init - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum); - - //Aim to increase block - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("Close BlockNumber:", blockNum + 1) - await ctx.DODOIncentive.methods.switchIncentive(0).send(ctx.sendParam(ctx.Deployer)); - totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("Close incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum) - //Aim to increase block - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - - blockNum = await ctx.Web3.eth.getBlockNumber(); - await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer)); - console.log("Open BlockNumber:", blockNum + 1) - //Aim to increase block - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); - totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("End incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum) - assert(totalReward, decimalStr("100")); - }); - - it("incentive-changeBoost with trade", async () => { - await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); - var totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - var blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("Init - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum); - - //Aim to increase block - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("Change BlockNumber:", blockNum + 1) - await ctx.DODOIncentive.methods.changePerReward(decimalStr("20")).send(ctx.sendParam(ctx.Deployer)); - totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("change incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum) - - //Aim to increase block - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.mintToken(ctx.DODO, null, lp, decimalStr("100"), mweiStr("0")); - await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); - totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - blockNum = await ctx.Web3.eth.getBlockNumber(); - console.log("End incentive - Total Reward:" + fromWei(totalReward, 'ether') + "; Total distribution:" + fromWei(totalDistribution, 'ether') + "; BlockNumber:" + blockNum) - assert(totalReward, decimalStr("140")); - }); - - it("directly swap with incentive", async () => { - await ctx.mintToken(ctx.DODO, ctx.USDT, trader, decimalStr("1000"), mweiStr("0")); - var b_DODO = await ctx.DODO.methods.balanceOf(trader).call() - var b_USDT = await ctx.USDT.methods.balanceOf(trader).call() - console.log("Before DODO:" + fromWei(b_DODO, 'ether') + "; USDT:" + fromWei(b_USDT, 'mwei')); - - var b_totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - var b_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - console.log("Before Total Reward:" + fromWei(b_totalReward, 'ether') + "; Total distribution:" + fromWei(b_totalDistribution, 'ether')) - - //approve DODO entry - await ctx.DODO.methods.approve(ctx.DODOApprove.options.address, MAX_UINT256).send(ctx.sendParam(trader)) - //set route path - var routes = [{ - address: ctx.DODO.options.address, - decimals: 18 - }, - { - address: ctx.USDT.options.address, - decimals: 6 - }]; - - var pairs = [{ - pair: ctx.DODO_USDT.options.address, - base: ctx.DODO.options.address, - pairContract: ctx.DODO_USDT - }]; - await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, false), ctx.sendParam(trader), "directly swap without incentive first") - await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, false), ctx.sendParam(trader), "directly swap without incentive second") - var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() - var a_USDT = await ctx.USDT.methods.balanceOf(trader).call() - console.log("After No Incentive DODO:" + fromWei(a_DODO, 'ether') + "; USDT:" + fromWei(a_USDT, 'mwei')); - - await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, true), ctx.sendParam(trader), "directly swap with incentive first") - await logGas(await calcRoute(ctx, decimalStr('10'), 0.1, routes, pairs, true), ctx.sendParam(trader), "directly swap with incentive second") - - var a_totalReward = await ctx.DODOIncentive.methods.totalReward().call(); - var a_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); - console.log("After Total Reward:" + fromWei(a_totalReward, 'ether') + "; Total distribution:" + fromWei(a_totalDistribution, 'ether')) - - a_DODO = await ctx.DODO.methods.balanceOf(trader).call() - a_USDT = await ctx.USDT.methods.balanceOf(trader).call() - console.log("After Incentive DODO:" + fromWei(a_DODO, 'ether') + "; USDT:" + fromWei(a_USDT, 'mwei')); - assert(a_DODO, decimalStr("961.493")); - }); - }); -}); diff --git a/test/V1/Admin.test.ts b/test/V1/Admin.test.ts deleted file mode 100644 index 4d750ef..0000000 --- a/test/V1/Admin.test.ts +++ /dev/null @@ -1,633 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import * as assert from 'assert'; - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr } from './utils/Converter'; - -let lp1: string; -let lp2: string; -let trader: string; -let tempAccount: string; - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")); - tempAccount = ctx.spareAccounts[5]; - lp1 = ctx.spareAccounts[0]; - lp2 = ctx.spareAccounts[1]; - trader = ctx.spareAccounts[2]; - await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000")); - await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000")); - await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000")); - await ctx.approveDODO(lp1); - await ctx.approveDODO(lp2); - await ctx.approveDODO(trader); -} - -describe("Admin", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("Settings", () => { - it("set oracle", async () => { - await ctx.DODO.methods - .setOracle(tempAccount) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._ORACLE_().call(), tempAccount); - }); - - it("set suprevisor", async () => { - await ctx.DODO.methods - .setSupervisor(tempAccount) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._SUPERVISOR_().call(), tempAccount); - }); - - it("set maintainer", async () => { - await ctx.DODO.methods - .setMaintainer(tempAccount) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._MAINTAINER_().call(), tempAccount); - }); - - it("set liquidity provider fee rate", async () => { - await ctx.DODO.methods - .setLiquidityProviderFeeRate(decimalStr("0.01")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal( - await ctx.DODO.methods._LP_FEE_RATE_().call(), - decimalStr("0.01") - ); - }); - - it("set maintainer fee rate", async () => { - await ctx.DODO.methods - .setMaintainerFeeRate(decimalStr("0.01")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal( - await ctx.DODO.methods._MT_FEE_RATE_().call(), - decimalStr("0.01") - ); - }); - - it("set k", async () => { - await ctx.DODO.methods - .setK(decimalStr("0.2")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._K_().call(), decimalStr("0.2")); - }); - - it("set gas price limit", async () => { - await ctx.DODO.methods - .setGasPriceLimit(decimalStr("100")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal( - await ctx.DODO.methods._GAS_PRICE_LIMIT_().call(), - decimalStr("100") - ); - }); - }); - - describe("Controls", () => { - it("control flow", async () => { - await ctx.DODO.methods - .disableBaseDeposit() - .send(ctx.sendParam(ctx.Supervisor)); - await assert.rejects( - ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)), - /DEPOSIT_BASE_NOT_ALLOWED/ - ); - - await ctx.DODO.methods - .enableBaseDeposit() - .send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - decimalStr("10") - ); - - await ctx.DODO.methods - .disableQuoteDeposit() - .send(ctx.sendParam(ctx.Supervisor)); - await assert.rejects( - ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)), - /DEPOSIT_QUOTE_NOT_ALLOWED/ - ); - - await ctx.DODO.methods - .enableQuoteDeposit() - .send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods - .depositQuote(decimalStr("10")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - decimalStr("10") - ); - - await ctx.DODO.methods - .disableTrading() - .send(ctx.sendParam(ctx.Supervisor)); - await assert.rejects( - ctx.DODO.methods - .buyBaseToken(decimalStr("1"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)), - /TRADE_NOT_ALLOWED/ - ); - - await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("1"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("101") - ); - }); - - it("control flow premission", async () => { - await assert.rejects( - ctx.DODO.methods.setGasPriceLimit("1").send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.disableTrading().send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.disableQuoteDeposit().send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.disableBaseDeposit().send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.disableBuying().send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.disableSelling().send(ctx.sendParam(trader)), - /NOT_SUPERVISOR_OR_OWNER/ - ); - - await assert.rejects( - ctx.DODO.methods.setOracle(trader).send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.setSupervisor(trader).send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.setMaintainer(trader).send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods - .setLiquidityProviderFeeRate(decimalStr("0.1")) - .send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods - .setMaintainerFeeRate(decimalStr("0.1")) - .send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.setK(decimalStr("0.1")).send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - - await assert.rejects( - ctx.DODO.methods.enableTrading().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.enableBuying().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.enableSelling().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods - .setBaseBalanceLimit(decimalStr("0")) - .send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods - .setQuoteBalanceLimit(decimalStr("0")) - .send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods.enableTrading().send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - }); - - it("advanced controls", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("10")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .disableBuying() - .send(ctx.sendParam(ctx.Supervisor)); - await assert.rejects( - ctx.DODO.methods - .buyBaseToken(decimalStr("1"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)), - /BUYING_NOT_ALLOWED/ - ); - await ctx.DODO.methods.enableBuying().send(ctx.sendParam(ctx.Deployer)); - - await ctx.DODO.methods - .disableSelling() - .send(ctx.sendParam(ctx.Supervisor)); - await assert.rejects( - ctx.DODO.methods - .sellBaseToken(decimalStr("1"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)), - /SELLING_NOT_ALLOWED/ - ); - await ctx.DODO.methods.enableSelling().send(ctx.sendParam(ctx.Deployer)); - - await ctx.DODO.methods - .setBaseBalanceLimit(decimalStr("0")) - .send(ctx.sendParam(ctx.Deployer)); - await assert.rejects( - ctx.DODO.methods - .depositBase(decimalStr("1000")) - .send(ctx.sendParam(lp1)), - /BASE_BALANCE_LIMIT_EXCEEDED/ - ); - - await ctx.DODO.methods - .setQuoteBalanceLimit(decimalStr("0")) - .send(ctx.sendParam(ctx.Deployer)); - await assert.rejects( - ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)), - /QUOTE_BALANCE_LIMIT_EXCEEDED/ - ); - }); - }); - - describe("Final settlement", () => { - it("final settlement when R is ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("100") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("10000") - ); - }); - - it("final settlement when R is ABOVE ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("94.995") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - "10551951805416248746110" - ); - }); - - it("final settlement when R is BELOW ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("100"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("105") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - "9540265973590798352835" - ); - }); - - it("final settlement when only deposit base", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("100") - ); - }); - - it("final settlement when only deposit quote", async () => { - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)); - - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("10000") - ); - }); - - it("final settlement revert cases", async () => { - await assert.rejects( - ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp1)), - /DODO_NOT_CLOSED/ - ); - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("500")) - .send(ctx.sendParam(lp2)); - - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .finalSettlement() - .send(ctx.sendParam(ctx.Deployer)); - await assert.rejects( - ctx.DODO.methods.finalSettlement().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - - await assert.rejects( - ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)), - /DODO_CLOSED/ - ) - await assert.rejects( - ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)), - /DODO_CLOSED/ - ) - - await ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp2)); - await assert.rejects( - ctx.DODO.methods.claimAssets().send(ctx.sendParam(lp2)), - /ALREADY_CLAIMED/ - ); - - await assert.rejects( - ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - await assert.rejects( - ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - await assert.rejects( - ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - await assert.rejects( - ctx.DODO.methods.enableBuying().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - await assert.rejects( - ctx.DODO.methods.enableSelling().send(ctx.sendParam(ctx.Deployer)), - /DODO_CLOSED/ - ); - }); - }); - - describe("donate", () => { - it("donate quote & base token", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositBase(decimalStr("20")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("2000")) - .send(ctx.sendParam(lp2)); - - await ctx.DODO.methods - .donateBaseToken(decimalStr("2")) - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .donateQuoteToken(decimalStr("500")) - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10666666666666666666" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "1166666666666666666666" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - "21333333333333333333" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - "2333333333333333333333" - ); - - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)); - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2)); - - await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)); - await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - "100666666666666666666" - ); - assert.equal( - await ctx.BASE.methods.balanceOf(lp2).call(), - "101333333333333333334" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - "10166666666666666666666" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp2).call(), - "10333333333333333333334" - ); - }); - }); - - describe("retrieve", () => { - it("retrieve base token", async () => { - await ctx.BASE.methods - .transfer(ctx.DODO.options.address, decimalStr("1")) - .send(ctx.sendParam(trader)); - await assert.rejects( - ctx.DODO.methods - .retrieve(ctx.BASE.options.address, decimalStr("1")) - .send(ctx.sendParam(trader)), - /NOT_OWNER/ - ); - await assert.rejects( - ctx.DODO.methods - .retrieve(ctx.BASE.options.address, decimalStr("2")) - .send(ctx.sendParam(ctx.Deployer)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - await ctx.DODO.methods - .retrieve(ctx.BASE.options.address, decimalStr("1")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Deployer).call(), - decimalStr("1") - ); - }); - - it("retrieve quote token", async () => { - await ctx.QUOTE.methods - .transfer(ctx.DODO.options.address, decimalStr("1")) - .send(ctx.sendParam(trader)); - await assert.rejects( - ctx.DODO.methods - .retrieve(ctx.QUOTE.options.address, decimalStr("2")) - .send(ctx.sendParam(ctx.Deployer)), - /DODO_QUOTE_BALANCE_NOT_ENOUGH/ - ); - await ctx.DODO.methods - .retrieve(ctx.QUOTE.options.address, decimalStr("1")) - .send(ctx.sendParam(ctx.Deployer)); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(), - decimalStr("1") - ); - }); - }); - - describe("revert cases", () => { - it("k revert cases", async () => { - await assert.rejects( - ctx.DODO.methods - .setK(decimalStr("1")) - .send(ctx.sendParam(ctx.Deployer)), - /K>=1/ - ); - await assert.rejects( - ctx.DODO.methods - .setK(decimalStr("0")) - .send(ctx.sendParam(ctx.Deployer)), - /K=0/ - ); - }); - - it("fee revert cases", async () => { - await assert.rejects( - ctx.DODO.methods - .setLiquidityProviderFeeRate(decimalStr("0.999")) - .send(ctx.sendParam(ctx.Deployer)), - /FEE_RATE>=1/ - ); - await assert.rejects( - ctx.DODO.methods - .setMaintainerFeeRate(decimalStr("0.998")) - .send(ctx.sendParam(ctx.Deployer)), - /FEE_RATE>=1/ - ); - }); - }); -}); diff --git a/test/V1/Attacks.test.ts b/test/V1/Attacks.test.ts deleted file mode 100644 index 8bb42b5..0000000 --- a/test/V1/Attacks.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr, gweiStr } from './utils/Converter'; -import BigNumber from "bignumber.js"; -import * as assert from "assert" - -let lp1: string -let lp2: string -let trader: string -let hacker: string - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")) - lp1 = ctx.spareAccounts[0] - lp2 = ctx.spareAccounts[1] - trader = ctx.spareAccounts[2] - hacker = ctx.spareAccounts[3] - await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000")) - await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000")) - await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000")) - await ctx.mintTestToken(hacker, decimalStr("10000"), decimalStr("1000000")) - await ctx.approveDODO(lp1) - await ctx.approveDODO(lp2) - await ctx.approveDODO(trader) - await ctx.approveDODO(hacker) -} - -describe("Attacks", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - ctx = await getDODOContext() - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - describe("Price offset attack", () => { - /* - attack describe: - 1. hacker deposit a great number of base token - 2. hacker buy base token - 3. hacker withdraw a great number of base token - 4. hacker sell or buy base token to finish the arbitrage loop - - expected: - 1. hacker won't earn any quote token or sell base token with price better than what dodo provides - 2. quote token lp and base token lp have no loss - - Same in quote direction - */ - it("attack on base token", async () => { - await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)) - await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1)) - let hackerInitBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - let hackerInitQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call()) - // attack step 1 - await ctx.DODO.methods.depositBase(decimalStr("5000")).send(ctx.sendParam(hacker)) - // attack step 2 - await ctx.DODO.methods.buyBaseToken(decimalStr("9.5"), decimalStr("2000"), "0x").send(ctx.sendParam(hacker)) - // attack step 3 - await ctx.DODO.methods.withdrawBase(decimalStr("5000")).send(ctx.sendParam(hacker)) - // attack step 4 - let hackerTempBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - if (hackerTempBaseBalance.isGreaterThan(hackerInitBaseBalance)) { - await ctx.DODO.methods.sellBaseToken(hackerTempBaseBalance.minus(hackerInitBaseBalance).toString(), "0", "0x").send(ctx.sendParam(hacker)) - } else { - await ctx.DODO.methods.buyBaseToken(hackerInitBaseBalance.minus(hackerTempBaseBalance).toString(), decimalStr("5000"), "0x").send(ctx.sendParam(hacker)) - } - - // expected hacker no profit - let hackerBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - let hackerQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call()) - - assert.ok(hackerBaseBalance.isLessThanOrEqualTo(hackerInitBaseBalance)) - assert.ok(hackerQuoteBalance.isLessThanOrEqualTo(hackerInitQuoteBalance)) - - // expected lp no loss - let lpBaseBalance = new BigNumber(await ctx.DODO.methods.getLpBaseBalance(lp1).call()) - let lpQuoteBalance = new BigNumber(await ctx.DODO.methods.getLpQuoteBalance(lp1).call()) - - assert.ok(lpBaseBalance.isGreaterThanOrEqualTo(decimalStr("10"))) - assert.ok(lpQuoteBalance.isGreaterThanOrEqualTo(decimalStr("1000"))) - }) - - it("attack on quote token", async () => { - await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)) - await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1)) - let hackerInitBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - let hackerInitQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call()) - - // attack step 1 - await ctx.DODO.methods.depositQuote(decimalStr("100000")).send(ctx.sendParam(hacker)) - // attack step 2 - await ctx.DODO.methods.sellBaseToken(decimalStr("9"), decimalStr("500"), "0x").send(ctx.sendParam(hacker)) - // attack step 3 - await ctx.DODO.methods.withdrawQuote(decimalStr("100000")).send(ctx.sendParam(hacker)) - // attack step 4 - let hackerTempBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - if (hackerTempBaseBalance.isGreaterThan(hackerInitBaseBalance)) { - await ctx.DODO.methods.sellBaseToken(hackerTempBaseBalance.minus(hackerInitBaseBalance).toString(), "0", "0x").send(ctx.sendParam(hacker)) - } else { - await ctx.DODO.methods.buyBaseToken(hackerInitBaseBalance.minus(hackerTempBaseBalance).toString(), decimalStr("5000"), "0x").send(ctx.sendParam(hacker)) - } - - // expected hacker no profit - let hackerBaseBalance = new BigNumber(await ctx.BASE.methods.balanceOf(hacker).call()) - let hackerQuoteBalance = new BigNumber(await ctx.QUOTE.methods.balanceOf(hacker).call()) - - assert.ok(hackerBaseBalance.isLessThanOrEqualTo(hackerInitBaseBalance)) - assert.ok(hackerQuoteBalance.isLessThanOrEqualTo(hackerInitQuoteBalance)) - - // expected lp no loss - let lpBaseBalance = new BigNumber(await ctx.DODO.methods.getLpBaseBalance(lp1).call()) - let lpQuoteBalance = new BigNumber(await ctx.DODO.methods.getLpQuoteBalance(lp1).call()) - - assert.ok(lpBaseBalance.isGreaterThanOrEqualTo(decimalStr("10"))) - assert.ok(lpQuoteBalance.isGreaterThanOrEqualTo(decimalStr("1000"))) - }) - }) - - describe("Front run attack", () => { - /* - attack describe: - hacker tries to front run oracle updating by sending tx with higher gas price - - expected: - revert tx - */ - it("front run", async () => { - await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp1)) - await ctx.DODO.methods.depositQuote(decimalStr("1000")).send(ctx.sendParam(lp1)) - await assert.rejects( - ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("200"), "0x").send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), /GAS_PRICE_EXCEED/ - ) - await assert.rejects( - ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("200"), "0x").send({ from: trader, gas: 300000, gasPrice: gweiStr("200") }), /GAS_PRICE_EXCEED/ - ) - }) - - }) - -}) \ No newline at end of file diff --git a/test/V1/DODOEthProxyAsBase.test.ts b/test/V1/DODOEthProxyAsBase.test.ts deleted file mode 100644 index 06c6a8d..0000000 --- a/test/V1/DODOEthProxyAsBase.test.ts +++ /dev/null @@ -1,233 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ -import * as assert from 'assert'; -import { BigNumber } from 'bignumber.js'; -import { TransactionReceipt } from 'web3-core'; -import { Contract } from 'web3-eth-contract'; - -import { - DefaultDODOContextInitConfig, - DODOContext, - getDODOContext, -} from './utils/DVMContext'; -import * as contracts from './utils/Contracts'; -import { decimalStr, MAX_UINT256 } from './utils/Converter'; -import { logGas } from './utils/Log'; - -let lp: string; -let trader: string; -let DODOEthProxy: Contract; - -async function init(ctx: DODOContext): Promise { - // switch ctx to eth proxy mode - const WETH = await contracts.newContract(contracts.WETH_CONTRACT_NAME); - await ctx.DODOZoo.methods - .breedDODO( - ctx.Maintainer, - WETH.options.address, - ctx.QUOTE.options.address, - ctx.ORACLE.options.address, - DefaultDODOContextInitConfig.lpFeeRate, - DefaultDODOContextInitConfig.mtFeeRate, - DefaultDODOContextInitConfig.k, - DefaultDODOContextInitConfig.gasPriceLimit - ) - .send(ctx.sendParam(ctx.Deployer)); - - ctx.DODO = contracts.getContractWithAddress( - contracts.DODO_CONTRACT_NAME, - await ctx.DODOZoo.methods - .getDODO(WETH.options.address, ctx.QUOTE.options.address) - .call() - ); - await ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer)); - - ctx.BASE = WETH; - - DODOEthProxy = await contracts.newContract( - contracts.DODO_ETH_PROXY_CONTRACT_NAME, - [ctx.DODOZoo.options.address, WETH.options.address] - ); - - // env - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - await ctx.setOraclePrice(decimalStr("100")); - await ctx.approveDODO(lp); - await ctx.approveDODO(trader); - - await ctx.QUOTE.methods - .mint(lp, decimalStr("1000")) - .send(ctx.sendParam(ctx.Deployer)); - await ctx.QUOTE.methods - .mint(trader, decimalStr("1000")) - .send(ctx.sendParam(ctx.Deployer)); - await ctx.QUOTE.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(trader)); - - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp)); -} - -describe("DODO ETH PROXY", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - await ctx.QUOTE.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(trader)); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - const depositAmount = "10"; - await DODOEthProxy.methods - .depositEthAsBase(decimalStr(depositAmount), ctx.QUOTE.options.address) - .send(ctx.sendParam(lp, depositAmount)); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("buy&sell eth directly", () => { - it("buy", async () => { - const buyAmount = "1"; - await logGas( - DODOEthProxy.methods.buyEthWithToken( - ctx.QUOTE.options.address, - decimalStr(buyAmount), - decimalStr("200") - ), - ctx.sendParam(trader), - "buy ETH with token directly" - ); - assert.strictEqual( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("8.999") - ); - assert.strictEqual( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "898581839502056240973" - ); - }); - it("sell", async () => { - const sellAmount = "1"; - await logGas( - DODOEthProxy.methods.sellEthToToken( - ctx.QUOTE.options.address, - decimalStr(sellAmount), - decimalStr("50") - ), - ctx.sendParam(trader, sellAmount), - "sell ETH to token directly" - ); - assert.strictEqual( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("11") - ); - assert.strictEqual( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1098617454226610630663" - ); - }); - }); - - describe("withdraw eth directly", () => { - it("withdraw", async () => { - const withdrawAmount = decimalStr("5"); - const baseLpTokenAddress = await ctx.DODO.methods - ._BASE_CAPITAL_TOKEN_() - .call(); - const baseLpToken = contracts.getContractWithAddress( - contracts.TEST_ERC20_CONTRACT_NAME, - baseLpTokenAddress - ); - await baseLpToken.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(lp)); - const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp); - const txReceipt: TransactionReceipt = await DODOEthProxy.methods - .withdrawEthAsBase(withdrawAmount, ctx.QUOTE.options.address) - .send(ctx.sendParam(lp)); - - assert.strictEqual( - await ctx.DODO.methods.getLpBaseBalance(lp).call(), - withdrawAmount - ); - const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash); - const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed); - const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp); - assert.ok( - new BigNumber(lpEthBalanceBefore) - .plus(withdrawAmount) - .minus(ethSpentOnGas) - .eq(lpEthBalanceAfter) - ); - }); - - it("withdraw all", async () => { - const withdrawAmount = decimalStr("10"); - const baseLpTokenAddress = await ctx.DODO.methods - ._BASE_CAPITAL_TOKEN_() - .call(); - const baseLpToken = contracts.getContractWithAddress( - contracts.TEST_ERC20_CONTRACT_NAME, - baseLpTokenAddress - ); - await baseLpToken.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(lp)); - const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp); - const txReceipt: TransactionReceipt = await DODOEthProxy.methods - .withdrawAllEthAsBase(ctx.QUOTE.options.address) - .send(ctx.sendParam(lp)); - - assert.strictEqual( - await ctx.DODO.methods.getLpBaseBalance(lp).call(), - "0" - ); - const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash); - const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed); - const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp); - assert.ok( - new BigNumber(lpEthBalanceBefore) - .plus(withdrawAmount) - .minus(ethSpentOnGas) - .eq(lpEthBalanceAfter) - ); - }); - }); - - describe("revert cases", () => { - it("value not match", async () => { - await assert.rejects( - DODOEthProxy.methods - .sellEthToToken( - ctx.QUOTE.options.address, - decimalStr("1"), - decimalStr("50") - ) - .send(ctx.sendParam(trader, "2")), - /ETH_AMOUNT_NOT_MATCH/ - ); - await assert.rejects( - DODOEthProxy.methods - .depositEthAsBase(decimalStr("1"), ctx.QUOTE.options.address) - .send(ctx.sendParam(lp, "2")), - /ETH_AMOUNT_NOT_MATCH/ - ); - }); - }); -}); diff --git a/test/V1/DODOEthProxyAsQuote.test.ts b/test/V1/DODOEthProxyAsQuote.test.ts deleted file mode 100644 index 9345c96..0000000 --- a/test/V1/DODOEthProxyAsQuote.test.ts +++ /dev/null @@ -1,247 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ -import * as assert from 'assert'; -import BigNumber from 'bignumber.js'; -import { TransactionReceipt } from 'web3-core'; -import { Contract } from 'web3-eth-contract'; - -import { - DefaultDODOContextInitConfig, - DODOContext, - getDODOContext, -} from './utils/DVMContext'; -import * as contracts from './utils/Contracts'; -import { decimalStr, MAX_UINT256 } from './utils/Converter'; -import { logGas } from './utils/Log'; - -let lp: string; -let trader: string; -let DODOEthProxy: Contract; - -async function init(ctx: DODOContext): Promise { - // switch ctx to eth proxy mode - const WETH = await contracts.newContract(contracts.WETH_CONTRACT_NAME); - await ctx.DODOZoo.methods - .breedDODO( - ctx.Maintainer, - ctx.BASE.options.address, - WETH.options.address, - ctx.ORACLE.options.address, - DefaultDODOContextInitConfig.lpFeeRate, - DefaultDODOContextInitConfig.mtFeeRate, - DefaultDODOContextInitConfig.k, - DefaultDODOContextInitConfig.gasPriceLimit - ) - .send(ctx.sendParam(ctx.Deployer)); - - ctx.DODO = contracts.getContractWithAddress( - contracts.DODO_CONTRACT_NAME, - await ctx.DODOZoo.methods - .getDODO(ctx.BASE.options.address, WETH.options.address) - .call() - ); - await ctx.DODO.methods.enableBaseDeposit().send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods.enableQuoteDeposit().send(ctx.sendParam(ctx.Deployer)); - await ctx.DODO.methods.enableTrading().send(ctx.sendParam(ctx.Deployer)); - - ctx.QUOTE = WETH; - - DODOEthProxy = await contracts.newContract( - contracts.DODO_ETH_PROXY_CONTRACT_NAME, - [ctx.DODOZoo.options.address, WETH.options.address] - ); - - // env - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - await ctx.setOraclePrice(decimalStr("0.01")); - await ctx.approveDODO(lp); - await ctx.approveDODO(trader); - - await ctx.BASE.methods - .mint(lp, decimalStr("1000")) - .send(ctx.sendParam(ctx.Deployer)); - await ctx.BASE.methods - .mint(trader, decimalStr("1000")) - .send(ctx.sendParam(ctx.Deployer)); - await ctx.BASE.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(trader)); - - await ctx.DODO.methods - .depositBase(decimalStr("1000")) - .send(ctx.sendParam(lp)); -} - -describe("DODO ETH PROXY", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - await ctx.BASE.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(trader)); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - let depositAmount = "10"; - await DODOEthProxy.methods - .depositEthAsQuote(decimalStr(depositAmount), ctx.BASE.options.address) - .send(ctx.sendParam(lp, depositAmount)); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("buy&sell eth directly", () => { - it("buy", async () => { - const maxPayEthAmount = "2.1"; - const ethInPoolBefore = decimalStr("10"); - const traderEthBalanceBefore = await ctx.Web3.eth.getBalance(trader); - const txReceipt: TransactionReceipt = await logGas( - DODOEthProxy.methods.buyTokenWithEth( - ctx.BASE.options.address, - decimalStr("200"), - decimalStr(maxPayEthAmount) - ), - ctx.sendParam(trader, maxPayEthAmount), - "buy token with ETH directly" - ); - const ethInPoolAfter = "12056338203652739553"; - assert.strictEqual( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - ethInPoolAfter - ); - assert.strictEqual( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("1200") - ); - const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash); - const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed); - const traderEthBalanceAfter = await ctx.Web3.eth.getBalance(trader); - - const totalEthBefore = new BigNumber(traderEthBalanceBefore).plus( - ethInPoolBefore - ); - const totalEthAfter = new BigNumber(traderEthBalanceAfter) - .plus(ethSpentOnGas) - .plus(ethInPoolAfter); - assert.ok(totalEthBefore.eq(totalEthAfter)); - }); - it("sell", async () => { - const minReceiveEthAmount = "0.45"; - await logGas( - DODOEthProxy.methods.sellTokenToEth( - ctx.BASE.options.address, - decimalStr("50"), - decimalStr(minReceiveEthAmount) - ), - ctx.sendParam(trader), - "sell token to ETH directly" - ); - assert.strictEqual( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "9503598324131652490" - ); - assert.strictEqual( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("950") - ); - }); - }); - - describe("withdraw eth directly", () => { - it("withdraw", async () => { - const withdrawAmount = decimalStr("5"); - const quoteLpTokenAddress = await ctx.DODO.methods - ._QUOTE_CAPITAL_TOKEN_() - .call(); - const quoteLpToken = contracts.getContractWithAddress( - contracts.TEST_ERC20_CONTRACT_NAME, - quoteLpTokenAddress - ); - await quoteLpToken.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(lp)); - const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp); - const txReceipt: TransactionReceipt = await DODOEthProxy.methods - .withdrawEthAsQuote(withdrawAmount, ctx.BASE.options.address) - .send(ctx.sendParam(lp)); - - assert.strictEqual( - await ctx.DODO.methods.getLpQuoteBalance(lp).call(), - withdrawAmount - ); - const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash); - const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed); - const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp); - assert.ok( - new BigNumber(lpEthBalanceBefore) - .plus(withdrawAmount) - .minus(ethSpentOnGas) - .eq(lpEthBalanceAfter) - ); - }); - - it("withdraw all", async () => { - const withdrawAmount = decimalStr("10"); - const quoteLpTokenAddress = await ctx.DODO.methods - ._QUOTE_CAPITAL_TOKEN_() - .call(); - const quoteLpToken = contracts.getContractWithAddress( - contracts.TEST_ERC20_CONTRACT_NAME, - quoteLpTokenAddress - ); - await quoteLpToken.methods - .approve(DODOEthProxy.options.address, MAX_UINT256) - .send(ctx.sendParam(lp)); - const lpEthBalanceBefore = await ctx.Web3.eth.getBalance(lp); - const txReceipt: TransactionReceipt = await DODOEthProxy.methods - .withdrawAllEthAsQuote(ctx.BASE.options.address) - .send(ctx.sendParam(lp)); - - assert.strictEqual( - await ctx.DODO.methods.getLpQuoteBalance(lp).call(), - "0" - ); - const tx = await ctx.Web3.eth.getTransaction(txReceipt.transactionHash); - const ethSpentOnGas = new BigNumber(tx.gasPrice).times(txReceipt.gasUsed); - const lpEthBalanceAfter = await ctx.Web3.eth.getBalance(lp); - assert.ok( - new BigNumber(lpEthBalanceBefore) - .plus(withdrawAmount) - .minus(ethSpentOnGas) - .eq(lpEthBalanceAfter) - ); - }); - }); - - describe("revert cases", () => { - it("value not match", async () => { - await assert.rejects( - DODOEthProxy.methods - .buyTokenWithEth( - ctx.BASE.options.address, - decimalStr("50"), - decimalStr("1") - ) - .send(ctx.sendParam(trader, "2")), - /ETH_AMOUNT_NOT_MATCH/ - ); - await assert.rejects( - DODOEthProxy.methods - .depositEthAsQuote(decimalStr("1"), ctx.BASE.options.address) - .send(ctx.sendParam(lp, "2")), - /ETH_AMOUNT_NOT_MATCH/ - ); - }); - }); -}); diff --git a/test/V1/DODOZoo.test.ts b/test/V1/DODOZoo.test.ts deleted file mode 100644 index f4a5a3a..0000000 --- a/test/V1/DODOZoo.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import * as assert from "assert" -import { newContract, TEST_ERC20_CONTRACT_NAME, getContractWithAddress, DODO_CONTRACT_NAME } from './utils/Contracts'; - - -async function init(ctx: DODOContext): Promise { } - -describe("DODO ZOO", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - ctx = await getDODOContext() - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - describe("Breed new dodo", () => { - it("could not deploy the same dodo", async () => { - await assert.rejects( - ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, ctx.BASE.options.address, ctx.QUOTE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)), - /DODO_REGISTERED/ - ) - - await assert.rejects( - ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, ctx.QUOTE.options.address, ctx.BASE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)), - /DODO_REGISTERED/ - ) - }) - - it("breed new dodo", async () => { - let newBase = await newContract(TEST_ERC20_CONTRACT_NAME, ["AnotherBase", 18]) - let newQuote = await newContract(TEST_ERC20_CONTRACT_NAME, ["AnotherQuote", 18]) - await assert.rejects( - ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, newBase.options.address, newQuote.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Maintainer)), - /NOT_OWNER/ - ) - await ctx.DODOZoo.methods.breedDODO(ctx.Maintainer, newBase.options.address, newQuote.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)) - - let newDODO = getContractWithAddress(DODO_CONTRACT_NAME, await ctx.DODOZoo.methods.getDODO(newBase.options.address, newQuote.options.address).call()) - assert.equal(await newDODO.methods._BASE_TOKEN_().call(), newBase.options.address) - assert.equal(await newDODO.methods._QUOTE_TOKEN_().call(), newQuote.options.address) - - // could not init twice - await assert.rejects( - newDODO.methods.init(ctx.Deployer, ctx.Supervisor, ctx.Maintainer, ctx.QUOTE.options.address, ctx.BASE.options.address, ctx.ORACLE.options.address, "0", "0", "1", "0").send(ctx.sendParam(ctx.Deployer)), - /DODO_INITIALIZED/ - ) - - // console.log(await ctx.DODOZoo.methods.getDODOs().call()) - }) - - // it.only("remove dodo", async () => { - // console.log(await ctx.DODOZoo.methods.getDODOs().call()) - // await ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)) - // console.log(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call()) - // console.log(await ctx.DODOZoo.methods.getDODOs().call()) - // }) - - it("dodo register control flow", async () => { - await ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)) - assert.equal(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call(), "0x0000000000000000000000000000000000000000") - await assert.rejects( - ctx.DODOZoo.methods.removeDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)), - /DODO_NOT_REGISTERED/ - ) - await ctx.DODOZoo.methods.addDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)) - assert.equal(await ctx.DODOZoo.methods.getDODO(ctx.BASE.options.address, ctx.QUOTE.options.address).call(), ctx.DODO.options.address) - await assert.rejects( - ctx.DODOZoo.methods.addDODO(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)), - /DODO_REGISTERED/ - ) - }) - - }) -}) \ No newline at end of file diff --git a/test/V1/LiquidityProvider.test.ts b/test/V1/LiquidityProvider.test.ts deleted file mode 100644 index fbda240..0000000 --- a/test/V1/LiquidityProvider.test.ts +++ /dev/null @@ -1,925 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import * as assert from 'assert'; - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr } from './utils/Converter'; -import { logGas } from './utils/Log'; - -let lp1: string; -let lp2: string; -let trader: string; - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")); - lp1 = ctx.spareAccounts[0]; - lp2 = ctx.spareAccounts[1]; - trader = ctx.spareAccounts[2]; - await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000")); - await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000")); - await ctx.mintTestToken(trader, decimalStr("100"), decimalStr("10000")); - await ctx.approveDODO(lp1); - await ctx.approveDODO(lp2); - await ctx.approveDODO(trader); -} - -describe("LiquidityProvider", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("R equals to ONE", () => { - it("multi lp deposit & withdraw", async () => { - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("0") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("0") - ); - - await logGas( - ctx.DODO.methods.depositBase(decimalStr("10")), - ctx.sendParam(lp1), - "deposit base" - ); - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("90") - ); - await logGas( - ctx.DODO.methods.depositQuote(decimalStr("1000")), - ctx.sendParam(lp1), - "deposit quote" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("9000") - ); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - decimalStr("1000") - ); - - await ctx.DODO.methods - .depositBase(decimalStr("3")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .depositQuote(decimalStr("70")) - .send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - decimalStr("3") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - decimalStr("70") - ); - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("13") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - decimalStr("1070") - ); - - await ctx.DODO.methods - .withdrawBase(decimalStr("5")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("5") - ); - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("95") - ); - await ctx.DODO.methods - .withdrawQuote(decimalStr("100")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("900") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("9100") - ); - - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)); - assert.equal(await ctx.DODO.methods.getLpBaseBalance(lp1).call(), "0"); - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("100") - ); - await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)); - assert.equal(await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), "0"); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("10000") - ); - }); - }); - - describe("R is ABOVE ONE", () => { - it("deposit", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10010841132009222923" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - - await ctx.DODO.methods - .depositBase(decimalStr("5")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .depositQuote(decimalStr("100")) - .send(ctx.sendParam(lp2)); - - // lp1 & lp2 would both have profit because the curve becomes flatter - // but the withdraw penalty is greater than this free profit - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10163234422929069723" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - "5076114129127759292" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - decimalStr("100") - ); - - assert.equal( - await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(), - "228507420047606093" - ); - assert.equal( - await ctx.DODO.methods - .getWithdrawQuotePenalty(decimalStr("100")) - .call(), - "0" - ); - }); - - it("withdraw", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("4")).call(), - "1065045389392391665" - ); - assert.equal( - await ctx.DODO.methods - .getWithdrawQuotePenalty(decimalStr("100")) - .call(), - "0" - ); - - await ctx.DODO.methods - .withdrawBase(decimalStr("4")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - "92934954610607608335" - ); - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - "2060045389392391665" - ); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "7075045389392391665" - ); - - await ctx.DODO.methods - .withdrawQuote(decimalStr("100")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("9100") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1451951805416248746119" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - decimalStr("900") - ); - }); - }); - - describe("R is BELOW ONE", () => { - it("deposit", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "1000978629616255276996" - ); - - await ctx.DODO.methods - .depositQuote(decimalStr("500")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .depositBase(decimalStr("5")) - .send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "1012529270910521756641" - ); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - decimalStr("5") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - "505769674273013522654" - ); - - assert.equal( - await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(), - "0" - ); - assert.equal( - await ctx.DODO.methods - .getWithdrawQuotePenalty(decimalStr("500")) - .call(), - "17320315567280002300" - ); - }); - - it("withdraw", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("4")).call(), - "0" - ); - assert.equal( - await ctx.DODO.methods - .getWithdrawQuotePenalty(decimalStr("100")) - .call(), - "7389428846238900753" - ); - - await ctx.DODO.methods - .withdrawQuote(decimalStr("100")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - "9092610571153761099247" - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "447655402437037253588" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "908310739520405637520" - ); - - await ctx.DODO.methods - .withdrawBase(decimalStr("4")) - .send(ctx.sendParam(lp1)); - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("94") - ); - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("11") - ); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - decimalStr("6") - ); - }); - }); - - describe("Oracle changes", () => { - it("base side lp don't has pnl when R is BELOW ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.setOraclePrice(decimalStr("80")); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "914362409397559037208" - ); - - await ctx.setOraclePrice(decimalStr("120")); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - decimalStr("10") - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "1085284653936129406317" - ); - }); - - it("quote side lp don't has pnl when R is ABOVE ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("600"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.setOraclePrice(decimalStr("80")); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "11138732839027528597" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - - await ctx.setOraclePrice(decimalStr("120")); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "9234731968726215588" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - decimalStr("1000") - ); - }); - }); - - describe("Transfer lp token", () => { - it("transfer", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - - await ctx.BaseCapital.methods - .transfer(lp2, decimalStr("5")) - .send(ctx.sendParam(lp1)); - await ctx.QuoteCapital.methods - .transfer(lp2, decimalStr("5")) - .send(ctx.sendParam(lp1)); - - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2)); - await ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp2).call(), - decimalStr("105") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp2).call(), - decimalStr("10005") - ); - }); - }); - - describe("Deposit & transfer to other account", () => { - it("base token", async () => { - await ctx.DODO.methods - .depositBaseTo(lp2, decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .withdrawBaseTo(trader, decimalStr("5")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .withdrawAllBaseTo(ctx.Supervisor) - .send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp1).call(), - decimalStr("90") - ); - assert.equal( - await ctx.BASE.methods.balanceOf(lp2).call(), - decimalStr("100") - ); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("105") - ); - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Supervisor).call(), - decimalStr("5") - ); - }); - - it("quote token", async () => { - await ctx.DODO.methods - .depositQuoteTo(lp2, decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .withdrawQuoteTo(trader, decimalStr("500")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .withdrawAllQuoteTo(ctx.Supervisor) - .send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp1).call(), - decimalStr("9000") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(lp2).call(), - decimalStr("10000") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - decimalStr("10500") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Supervisor).call(), - decimalStr("500") - ); - }); - }); - - describe("Corner cases", () => { - it("single side deposit", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .sellBaseToken("5015841132009222923", decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "10010841132009222923" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1103903610832497492" - ); - - await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(), - "1103903610832497493" - ); - }); - - it("single side deposit & lp deposit when R isn't equal to ONE", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(), - "1" - ); - assert.equal(await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), "1"); - }); - - it("single side deposit (base) & oracle change introduces loss", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.setOraclePrice(decimalStr("120")); - await ctx.DODO.methods - .sellBaseToken(decimalStr("4"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("1"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2"); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "9234731968726215603" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1105993618321025490" - ); - - await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2)); - assert.equal( - await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(), - "7221653398290521828" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - "7221653398290521884" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "9234731968726215603" - ); - }); - - it("single side deposit (base) & oracle change introduces profit", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.setOraclePrice(decimalStr("80")); - await ctx.DODO.methods - .sellBaseToken(decimalStr("4"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("4"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2"); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "11138732839027528584" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1105408308382702868" - ); - - await ctx.DODO.methods.depositQuote("1").send(ctx.sendParam(lp2)); - assert.equal( - await ctx.DODO.methods.getQuoteCapitalBalanceOf(lp2).call(), - "21553269260529319669" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp2).call(), - "21553269260529319697" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "11138732839027528584" - ); - }); - - it("single side deposit (quote) & oracle change introduces loss", async () => { - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - await ctx.setOraclePrice(decimalStr("80")); - await ctx.DODO.methods - .buyBaseToken(decimalStr("4"), decimalStr("600"), "0x") - .send(ctx.sendParam(trader)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("0.99"), decimalStr("500"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "1"); - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "9980000000000000" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "914362409397559035414" - ); - - await ctx.DODO.methods.depositBase("1").send(ctx.sendParam(lp2)); - assert.equal( - await ctx.DODO.methods.getBaseCapitalBalanceOf(lp2).call(), - "10247647352975730" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - "10247647352975730" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp1).call(), - "914362409397559035414" - ); - }); - - it("deposit and withdraw immediately", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10010841132009222923" - ); - - await ctx.DODO.methods - .depositBase(decimalStr("5")) - .send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10163234422929069723" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp2).call(), - "5076114129127759292" - ); - - await ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp2)); - - assert.equal( - await ctx.BASE.methods.balanceOf(lp2).call(), - "99841132414635941792" - ); - assert.equal( - await ctx.DODO.methods.getLpBaseBalance(lp1).call(), - "10182702153814588648" - ); - }); - }); - - describe("Revert cases", () => { - it("withdraw base amount exceeds DODO balance", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("5"), decimalStr("1000"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods.withdrawBase(decimalStr("6")).send(ctx.sendParam(lp1)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - - await assert.rejects( - ctx.DODO.methods.withdrawAllBase().send(ctx.sendParam(lp1)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - }); - - it("withdraw quote amount exceeds DODO balance", async () => { - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("5"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .withdrawQuote(decimalStr("600")) - .send(ctx.sendParam(lp1)), - /DODO_QUOTE_BALANCE_NOT_ENOUGH/ - ); - - await assert.rejects( - ctx.DODO.methods.withdrawAllQuote().send(ctx.sendParam(lp1)), - /DODO_QUOTE_BALANCE_NOT_ENOUGH/ - ); - }); - - it("withdraw base could not afford penalty", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("9"), decimalStr("10000"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .withdrawBase(decimalStr("0.5")) - .send(ctx.sendParam(lp1)), - /PENALTY_EXCEED/ - ); - - await assert.rejects( - ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("10")).call(), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - }); - - it("withdraw quote could not afford penalty", async () => { - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("10"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .withdrawQuote(decimalStr("200")) - .send(ctx.sendParam(lp1)), - /PENALTY_EXCEED/ - ); - - await assert.rejects( - ctx.DODO.methods.getWithdrawQuotePenalty(decimalStr("1000")).call(), - /DODO_QUOTE_BALANCE_NOT_ENOUGH/ - ); - }); - - it("withdraw all base could not afford penalty", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("9.5")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositBase(decimalStr("0.5")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .buyBaseToken(decimalStr("9"), decimalStr("10000"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .withdrawBase(decimalStr("0.5")) - .send(ctx.sendParam(lp2)), - /PENALTY_EXCEED/ - ); - }); - - it("withdraw all quote could not afford penalty", async () => { - await ctx.DODO.methods - .depositQuote(decimalStr("800")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("200")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .sellBaseToken(decimalStr("10"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .withdrawQuote(decimalStr("200")) - .send(ctx.sendParam(lp2)), - /PENALTY_EXCEED/ - ); - }); - - it("withdraw amount exceeds lp balance", async () => { - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositBase(decimalStr("10")) - .send(ctx.sendParam(lp2)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp1)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp2)); - await assert.rejects( - ctx.DODO.methods - .withdrawBase(decimalStr("11")) - .send(ctx.sendParam(lp1)), - /LP_BASE_CAPITAL_BALANCE_NOT_ENOUGH/ - ); - await assert.rejects( - ctx.DODO.methods - .withdrawQuote(decimalStr("1100")) - .send(ctx.sendParam(lp1)), - /LP_QUOTE_CAPITAL_BALANCE_NOT_ENOUGH/ - ); - }); - - it("withdraw when there is no lp", async () => { - await assert.rejects( - ctx.DODO.methods.withdrawBase(decimalStr("1")).send(ctx.sendParam(lp1)), - /NO_BASE_LP/ - ); - await assert.rejects( - ctx.DODO.methods - .withdrawQuote(decimalStr("1")) - .send(ctx.sendParam(lp1)), - /NO_QUOTE_LP/ - ); - }); - }); -}); diff --git a/test/V1/LongTailTokenlMode.test.ts b/test/V1/LongTailTokenlMode.test.ts deleted file mode 100644 index 284c95c..0000000 --- a/test/V1/LongTailTokenlMode.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr, gweiStr } from './utils/Converter'; -import * as assert from "assert" - -let lp: string -let trader: string - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("10")) - - lp = ctx.spareAccounts[0] - trader = ctx.spareAccounts[1] - await ctx.approveDODO(lp) - await ctx.approveDODO(trader) - - await ctx.mintTestToken(lp, decimalStr("10000"), decimalStr("10000000")) - await ctx.mintTestToken(trader, decimalStr("0"), decimalStr("10000000")) - - await ctx.DODO.methods.depositBase(decimalStr("10000")).send(ctx.sendParam(lp)) -} - -describe("Trader", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - let dodoContextInitConfig = { - lpFeeRate: decimalStr("0"), - mtFeeRate: decimalStr("0"), - k: decimalStr("0.99"), // nearly one - gasPriceLimit: gweiStr("100"), - } - ctx = await getDODOContext(dodoContextInitConfig) - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - // price change quickly - describe("Trade long tail coin", () => { - it("price discover", async () => { - // 10% depth - // avg price = 11.137 - await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("1000")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9988900000000000000000000") - - // 20% depth - // avg price = 12.475 - await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("2000")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9975049999999999999970000") - - // 50% depth - // avg price = 19.9 - await ctx.DODO.methods.buyBaseToken(decimalStr("3000"), decimalStr("300000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("5000")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9900499999999999999970000") - - // 80% depth - // avg price = 49.6 - await ctx.DODO.methods.buyBaseToken(decimalStr("3000"), decimalStr("300000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("8000")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9603199999999999999970000") - }) - - it("user has no pnl if buy and sell immediately", async () => { - // lp buy - await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(lp)) - - // trader buy and sell - await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("100000"), "0x").send(ctx.sendParam(trader)) - await ctx.DODO.methods.sellBaseToken(decimalStr("1000"), decimalStr("0"), "0x").send(ctx.sendParam(trader)) - - // no profit or loss (may have precision problems) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), "0") - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9999999999999999999970000") - }) - }) -}) \ No newline at end of file diff --git a/test/V1/Mining.test.ts b/test/V1/Mining.test.ts deleted file mode 100644 index 70436bb..0000000 --- a/test/V1/Mining.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr, MAX_UINT256 } from './utils/Converter'; -// import * as assert from "assert" -import { newContract, DODO_TOKEN_CONTRACT_NAME, DODO_MINE_NAME, TEST_ERC20_CONTRACT_NAME, getContractWithAddress, DODO_MINE_READER_NAME } from './utils/Contracts'; -import { Contract } from 'web3-eth-contract'; -import { assert } from 'chai'; -import { logGas } from './utils/Log'; - -let BaseDLP: Contract -let QuoteDLP: Contract -let DODOToken: Contract -let DODOMine: Contract -let DODOMineReader: Contract -let lp1: string; -let lp2: string; - -async function init(ctx: DODOContext): Promise { - - lp1 = ctx.spareAccounts[0]; - lp2 = ctx.spareAccounts[1]; - await ctx.mintTestToken(lp1, decimalStr("100"), decimalStr("10000")); - await ctx.mintTestToken(lp2, decimalStr("100"), decimalStr("10000")); - - await ctx.approveDODO(lp1); - await ctx.approveDODO(lp2); - - await ctx.DODO.methods.depositBase(decimalStr("100")).send(ctx.sendParam(lp1)) - await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp1)) - - await ctx.DODO.methods.depositBase(decimalStr("100")).send(ctx.sendParam(lp2)) - await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp2)) - - DODOToken = await newContract(DODO_TOKEN_CONTRACT_NAME) - DODOMine = await newContract(DODO_MINE_NAME, [DODOToken.options.address, (await ctx.Web3.eth.getBlockNumber()).toString()]) - DODOMineReader = await newContract(DODO_MINE_READER_NAME) - - BaseDLP = await getContractWithAddress(TEST_ERC20_CONTRACT_NAME, await ctx.DODO.methods._BASE_CAPITAL_TOKEN_().call()) - QuoteDLP = await getContractWithAddress(TEST_ERC20_CONTRACT_NAME, await ctx.DODO.methods._QUOTE_CAPITAL_TOKEN_().call()) - - await BaseDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp1)) - await QuoteDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp1)) - - await BaseDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp2)) - await QuoteDLP.methods.approve(DODOMine.options.address, MAX_UINT256).send(ctx.sendParam(lp2)) - - await DODOMine.methods.setReward(decimalStr("100"), true).send(ctx.sendParam(ctx.Deployer)) - await DODOMine.methods.addLpToken(BaseDLP.options.address, "1", true).send(ctx.sendParam(ctx.Deployer)) - await DODOMine.methods.addLpToken(QuoteDLP.options.address, "2", true).send(ctx.sendParam(ctx.Deployer)) - - const rewardVault = await DODOMine.methods.dodoRewardVault().call() - await DODOToken.methods.transfer(rewardVault, decimalStr("100000000")).send(ctx.sendParam(ctx.Deployer)) -} - -describe("Lock DODO Token", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - ctx = await getDODOContext() - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - describe("Lp Deposit", () => { - it("single lp deposit", async () => { - await logGas(DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")), ctx.sendParam(lp1), "deposit") - await ctx.EVM.fastMove(100) - assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "3333333333333333333300") - assert.equal(await DODOMine.methods.getDlpMiningSpeed(BaseDLP.options.address).call(), "33333333333333333333") - }) - - it("multi lp deposit", async () => { - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await ctx.EVM.fastMove(100) - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2)) - await ctx.EVM.fastMove(100) - assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "5033333333333333333200") - assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp2).call(), "1666666666666666666600") - - await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await ctx.EVM.fastMove(100) - await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2)) - await ctx.EVM.fastMove(100) - assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp1).call(), "10066666666666666666600") - assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp2).call(), "3333333333333333333300") - - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "18466666666666666666500") - assert.equal(await DODOMine.methods.getAllPendingReward(lp2).call(), "8366666666666666666600") - }) - - it.only("lp multi deposit and withdraw", async () => { - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2)) - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await ctx.EVM.fastMove(100) - await logGas(DODOMine.methods.withdraw(BaseDLP.options.address, decimalStr("50")), ctx.sendParam(lp1), "withdraw") - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0") - assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "1683333333333333333300") - assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "1683333333333333333300") - await ctx.EVM.fastMove(100) - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("50")).send(ctx.sendParam(lp1)) - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0") - assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "2805555555555555555500") - assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "2805555555555555555500") - - var balance = await DODOMineReader.methods.getUserStakedBalance(DODOMine.options.address, ctx.DODO.options.address, lp1).call() - assert.equal(balance.baseBalance, decimalStr("100")) - assert.equal(balance.quoteBalance, decimalStr("0")) - }) - - it("lp claim", async () => { - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2)) - - await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp2)) - - await ctx.EVM.fastMove(100) - - await logGas(DODOMine.methods.claim(BaseDLP.options.address), ctx.sendParam(lp1), "claim") - assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp1).call(), "0") - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "3433333333333333333200") - assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "1749999999999999999900") - assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "1749999999999999999900") - - await logGas(DODOMine.methods.claimAll(), ctx.sendParam(lp2), "claim 2 pool") - assert.equal(await DODOMine.methods.getPendingReward(BaseDLP.options.address, lp2).call(), "0") - assert.equal(await DODOMine.methods.getAllPendingReward(lp2).call(), "0") - assert.equal(await DODOMine.methods.getRealizedReward(lp2).call(), "5133333333333333333200") - assert.equal(await DODOToken.methods.balanceOf(lp2).call(), "5133333333333333333200") - }) - - it("lp emergency withdraw", async () => { - await DODOMine.methods.deposit(QuoteDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - - await ctx.EVM.fastMove(100) - - await DODOMine.methods.emergencyWithdraw(QuoteDLP.options.address).send(ctx.sendParam(lp1)) - - assert.equal(await QuoteDLP.methods.balanceOf(lp1).call(), decimalStr("10000")) - assert.equal(await DODOMine.methods.getPendingReward(QuoteDLP.options.address, lp1).call(), "0") - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "0") - assert.equal(await DODOMine.methods.getRealizedReward(lp1).call(), "0") - assert.equal(await DODOToken.methods.balanceOf(lp1).call(), "0") - }) - - it("setLpToken", async () => { - await DODOMine.methods.deposit(BaseDLP.options.address, decimalStr("100")).send(ctx.sendParam(lp1)) - await ctx.EVM.fastMove(100) - await DODOMine.methods.setLpToken(BaseDLP.options.address, "2", true).send(ctx.sendParam(ctx.Deployer)) - await ctx.EVM.fastMove(100) - - assert.equal(await DODOMine.methods.getAllPendingReward(lp1).call(), "8366666666666666666600") - }) - - }) - -}) \ No newline at end of file diff --git a/test/V1/Rebalance.test.ts b/test/V1/Rebalance.test.ts deleted file mode 100644 index 5d953cf..0000000 --- a/test/V1/Rebalance.test.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import * as assert from 'assert'; -import { Contract } from 'web3-eth-contract'; - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { DODO_REBALANCER_NAME, newContract } from './utils/Contracts'; -import { decimalStr } from './utils/Converter'; - -let lp: string; -let trader: string; -let rebalancer: Contract; - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")); - - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - await ctx.approveDODO(lp); - await ctx.approveDODO(trader); - - await ctx.mintTestToken(lp, decimalStr("10"), decimalStr("1000")); - await ctx.mintTestToken(trader, decimalStr("10"), decimalStr("1000")); - - await ctx.DODO.methods - .depositBaseTo(lp, decimalStr("10")) - .send(ctx.sendParam(lp)); - await ctx.DODO.methods - .depositQuoteTo(lp, decimalStr("1000")) - .send(ctx.sendParam(lp)); - - rebalancer = await newContract(DODO_REBALANCER_NAME) -} - -describe("Trader", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("rebalance", () => { - it("R above ONE rebalance", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)) - await ctx.DODO.methods.disableTrading().send(ctx.sendParam(ctx.Deployer)) - await ctx.DODO.methods.transferOwnership(rebalancer.options.address).send(ctx.sendParam(ctx.Deployer)) - await rebalancer.methods.claimOwnership(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)) - - await ctx.BASE.methods.transfer(rebalancer.options.address, decimalStr("2")).send(ctx.sendParam(trader)) - await rebalancer.methods.rebalance(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)); - - assert.equal(await ctx.DODO.methods.getMidPrice().call(), await ctx.DODO.methods.getOraclePrice().call()) - - await rebalancer.methods.transferOwnership(ctx.DODO.options.address, ctx.Deployer).send(ctx.sendParam(ctx.Deployer)) - await ctx.DODO.methods.claimOwnership().send(ctx.sendParam(ctx.Deployer)) - - await rebalancer.methods.retrieve(ctx.BASE.options.address).send(ctx.sendParam(ctx.Deployer)) - await rebalancer.methods.retrieve(ctx.QUOTE.options.address).send(ctx.sendParam(ctx.Deployer)) - - assert.equal(await ctx.BASE.methods.balanceOf(ctx.Deployer).call(), "996997569110682237") - assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(), "101113906016449927750") - }); - - it("R below ONE rebalance", async () => { - await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader)) - await ctx.DODO.methods.disableTrading().send(ctx.sendParam(ctx.Deployer)) - await ctx.DODO.methods.transferOwnership(rebalancer.options.address).send(ctx.sendParam(ctx.Deployer)) - await rebalancer.methods.claimOwnership(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)) - - await ctx.QUOTE.methods.transfer(rebalancer.options.address, decimalStr("200")).send(ctx.sendParam(trader)) - await rebalancer.methods.rebalance(ctx.DODO.options.address).send(ctx.sendParam(ctx.Deployer)); - - assert.equal(await ctx.DODO.methods.getMidPrice().call(), await ctx.DODO.methods.getOraclePrice().call()) - - await rebalancer.methods.transferOwnership(ctx.DODO.options.address, ctx.Deployer).send(ctx.sendParam(ctx.Deployer)) - await ctx.DODO.methods.claimOwnership().send(ctx.sendParam(ctx.Deployer)) - - await rebalancer.methods.retrieve(ctx.BASE.options.address).send(ctx.sendParam(ctx.Deployer)) - await rebalancer.methods.retrieve(ctx.QUOTE.options.address).send(ctx.sendParam(ctx.Deployer)) - - assert.equal(await ctx.BASE.methods.balanceOf(ctx.Deployer).call(), "997008973080757726") - assert.equal(await ctx.QUOTE.methods.balanceOf(ctx.Deployer).call(), "101085569972088780856") - }); - - }); -}); diff --git a/test/V1/StableCoinMode.test.ts b/test/V1/StableCoinMode.test.ts deleted file mode 100644 index 84c5514..0000000 --- a/test/V1/StableCoinMode.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr, gweiStr } from './utils/Converter'; -import * as assert from "assert" - -let lp: string -let trader: string - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("1")) - - lp = ctx.spareAccounts[0] - trader = ctx.spareAccounts[1] - await ctx.approveDODO(lp) - await ctx.approveDODO(trader) - - await ctx.mintTestToken(lp, decimalStr("10000"), decimalStr("10000")) - await ctx.mintTestToken(trader, decimalStr("10000"), decimalStr("10000")) - - await ctx.DODO.methods.depositBase(decimalStr("10000")).send(ctx.sendParam(lp)) - await ctx.DODO.methods.depositQuote(decimalStr("10000")).send(ctx.sendParam(lp)) -} - -describe("Trader", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - let dodoContextInitConfig = { - lpFeeRate: decimalStr("0.0001"), - mtFeeRate: decimalStr("0"), - k: gweiStr("1"), // nearly zero - gasPriceLimit: gweiStr("100"), - } - ctx = await getDODOContext(dodoContextInitConfig) - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - describe("Trade stable coin", () => { - it("trade with tiny slippage", async () => { - // 10% depth avg price 1.000100000111135 - await ctx.DODO.methods.buyBaseToken(decimalStr("1000"), decimalStr("1001"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("11000")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "8999899999888865431655") - - // 99.9% depth avg price 1.00010109 - await ctx.DODO.methods.buyBaseToken(decimalStr("8990"), decimalStr("10000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("19990")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "8990031967806921648") - - // sell to 99.9% depth avg price 0.9999 - await ctx.DODO.methods.sellBaseToken(decimalStr("19980"), decimalStr("19970"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("10")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "19986992950440794518402") - }) - - it("huge sell trading amount", async () => { - // trader could sell any number of base token - // but the price will drop quickly - await ctx.mintTestToken(trader, decimalStr("10000"), decimalStr("0")) - await ctx.DODO.methods.sellBaseToken(decimalStr("20000"), decimalStr("0"), "0x").send(ctx.sendParam(trader)) - - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("0")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "19998999990001000029997") - }) - - it("huge buy trading amount", async () => { - // could not buy all base balance - await assert.rejects( - ctx.DODO.methods.buyBaseToken(decimalStr("10000"), decimalStr("10010"), "0x").send(ctx.sendParam(trader)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ) - - // when buy amount close to base balance, price will increase quickly - await ctx.mintTestToken(trader, decimalStr("0"), decimalStr("10000")) - await ctx.DODO.methods.buyBaseToken(decimalStr("9999"), decimalStr("20000"), "0x").send(ctx.sendParam(trader)) - assert.equal(await ctx.BASE.methods.balanceOf(trader).call(), decimalStr("19999")) - assert.equal(await ctx.QUOTE.methods.balanceOf(trader).call(), "9000000119999999900000") - }) - - it("tiny withdraw penalty", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("9990"), decimalStr("10000"), "0x").send(ctx.sendParam(trader)) - - // penalty only 0.2% even if withdraw make pool utilization rate raise to 99.5% - assert.equal(await ctx.DODO.methods.getWithdrawBasePenalty(decimalStr("5")).call(), "9981967500000000") - }) - }) -}) \ No newline at end of file diff --git a/test/V1/TokenLock.test.ts b/test/V1/TokenLock.test.ts deleted file mode 100644 index 6cd6f05..0000000 --- a/test/V1/TokenLock.test.ts +++ /dev/null @@ -1,184 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr, MAX_UINT256 } from './utils/Converter'; -// import * as assert from "assert" -import { newContract, DODO_TOKEN_CONTRACT_NAME, LOCKED_TOKEN_VAULT_CONTRACT_NAME } from './utils/Contracts'; -import { Contract } from 'web3-eth-contract'; -import * as assert from 'assert'; -import BigNumber from 'bignumber.js'; -import { logGas } from './utils/Log'; - -let DODOToken: Contract -let LockedTokenVault: Contract -let initTime: any - -let u1: string -let u2: string -let u3: string - -async function init(ctx: DODOContext): Promise { - u1 = ctx.spareAccounts[0]; - u2 = ctx.spareAccounts[1]; - u3 = ctx.spareAccounts[2]; - - initTime = (await ctx.Web3.eth.getBlock(await ctx.Web3.eth.getBlockNumber())).timestamp; - DODOToken = await newContract(DODO_TOKEN_CONTRACT_NAME) - - // release after 1 day, cliff 10% and vest in 1 day - LockedTokenVault = await newContract(LOCKED_TOKEN_VAULT_CONTRACT_NAME, [DODOToken.options.address, initTime + 86400, 86400, decimalStr("0.1")]) - - DODOToken.methods.approve(LockedTokenVault.options.address, MAX_UINT256).send(ctx.sendParam(ctx.Deployer)) - LockedTokenVault.methods.deposit(decimalStr("10000")).send(ctx.sendParam(ctx.Deployer)) -} - -describe("Lock DODO Token", () => { - - let snapshotId: string - let ctx: DODOContext - - before(async () => { - ctx = await getDODOContext() - await init(ctx); - }) - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId) - }); - - describe("Lock operations", () => { - it("init states", async () => { - assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("10000")) - await logGas(LockedTokenVault.methods.grant( - [u1], - [decimalStr("100")] - ), ctx.sendParam(ctx.Deployer), "grant 1 address") - }) - - it("grant", async () => { - await logGas(LockedTokenVault.methods.grant( - [u1, u2, u3], - [decimalStr("100"), decimalStr("200"), decimalStr("300")] - ), ctx.sendParam(ctx.Deployer), "grant 3 address") - - assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("9400")) - - assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100")) - assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), decimalStr("200")) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") - - await ctx.EVM.increaseTime(86400) - assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("10"))) - - await ctx.EVM.increaseTime(30000) - assert.ok(approxEqual(await LockedTokenVault.methods.getClaimableBalance(u1).call(), decimalStr("41.25"))) - }) - - it("claim", async () => { - await LockedTokenVault.methods.grant( - [u1, u2, u3], - [decimalStr("100"), decimalStr("200"), decimalStr("300")] - ).send(ctx.sendParam(ctx.Deployer)) - - await ctx.EVM.increaseTime(86400) - await LockedTokenVault.methods.claim().send(ctx.sendParam(u1)) - assert.equal(await LockedTokenVault.methods.getOriginBalance(u1).call(), decimalStr("100")) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") - assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("10"))) - - await ctx.EVM.increaseTime(30000) - await LockedTokenVault.methods.claim().send(ctx.sendParam(u1)) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u1).call(), "0") - assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u1).call(), decimalStr("58.75"))) - assert.ok(approxEqual(await DODOToken.methods.balanceOf(u1).call(), decimalStr("41.25"))) - - await LockedTokenVault.methods.claim().send(ctx.sendParam(u2)) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0") - assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("117.5"))) - assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("82.5"))) - }) - - it("recall & transfer", async () => { - await LockedTokenVault.methods.grant( - [u1, u2, u3], - [decimalStr("100"), decimalStr("200"), decimalStr("300")] - ).send(ctx.sendParam(ctx.Deployer)) - - // recall u2 - await LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer)) - assert.equal(await LockedTokenVault.methods.getOriginBalance(u2).call(), "0") - - // transfer from u3 to u2 - await ctx.EVM.increaseTime(86400 + 30000) - await LockedTokenVault.methods.transferLockedToken(u2).send(ctx.sendParam(u3)) - - await LockedTokenVault.methods.claim().send(ctx.sendParam(u2)) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u2).call(), "0") - assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u2).call(), decimalStr("176.25"))) - assert.ok(approxEqual(await DODOToken.methods.balanceOf(u2).call(), decimalStr("123.75"))) - - // transfer from u2 to u3 - await ctx.EVM.increaseTime(30000) - await LockedTokenVault.methods.transferLockedToken(u3).send(ctx.sendParam(u2)) - - await LockedTokenVault.methods.claim().send(ctx.sendParam(u3)) - assert.equal(await LockedTokenVault.methods.getClaimableBalance(u3).call(), "0") - assert.ok(approxEqual(await LockedTokenVault.methods.getRemainingBalance(u3).call(), decimalStr("82.5"))) - assert.ok(approxEqual(await DODOToken.methods.balanceOf(u3).call(), decimalStr("93.75"))) - - // transfer from u3 to u1 - await LockedTokenVault.methods.transferLockedToken(u1).send(ctx.sendParam(u3)) - - }) - - it("withdraw", async () => { - await LockedTokenVault.methods.grant( - [u1, u2, u3], - [decimalStr("100"), decimalStr("200"), decimalStr("300")] - ).send(ctx.sendParam(ctx.Deployer)) - - await LockedTokenVault.methods.withdraw(decimalStr("1000")).send(ctx.sendParam(ctx.Deployer)) - assert.equal(await LockedTokenVault.methods._UNDISTRIBUTED_AMOUNT_().call(), decimalStr("8400")) - - await assert.rejects( - LockedTokenVault.methods.withdraw(decimalStr("8500")).send(ctx.sendParam(ctx.Deployer)), - /SUB_ERROR/ - ) - }) - - it("finish distributed", async () => { - await LockedTokenVault.methods.grant( - [u1, u2, u3], - [decimalStr("100"), decimalStr("200"), decimalStr("300")] - ).send(ctx.sendParam(ctx.Deployer)) - await LockedTokenVault.methods.finishDistribute().send(ctx.sendParam(ctx.Deployer)) - - // can not recall - await assert.rejects( - LockedTokenVault.methods.recall(u2).send(ctx.sendParam(ctx.Deployer)), - /DISTRIBUTE FINISHED/ - ) - }) - }) - -}) - -function approxEqual(numStr1: string, numStr2: string) { - let num1 = new BigNumber(numStr1) - let num2 = new BigNumber(numStr2) - let ratio = num1.div(num2).minus(1).abs() - if (ratio.isLessThan(0.0002)) { - return true - } else { - return false - } -} \ No newline at end of file diff --git a/test/V1/Trader.test.ts b/test/V1/Trader.test.ts deleted file mode 100644 index fecc73c..0000000 --- a/test/V1/Trader.test.ts +++ /dev/null @@ -1,553 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import * as assert from 'assert'; - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { decimalStr } from './utils/Converter'; -import { logGas } from './utils/Log'; - -let lp: string; -let trader: string; - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")); - - lp = ctx.spareAccounts[0]; - trader = ctx.spareAccounts[1]; - await ctx.approveDODO(lp); - await ctx.approveDODO(trader); - - await ctx.mintTestToken(lp, decimalStr("10"), decimalStr("1000")); - await ctx.mintTestToken(trader, decimalStr("10"), decimalStr("1000")); - - await ctx.DODO.methods - .depositBaseTo(lp, decimalStr("10")) - .send(ctx.sendParam(lp)); - await ctx.DODO.methods - .depositQuoteTo(lp, decimalStr("1000")) - .send(ctx.sendParam(lp)); -} - -describe("Trader", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("R goes above ONE", () => { - it("buy when R equals ONE", async () => { - await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x"), ctx.sendParam(trader), "buy base token when balanced") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("11") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "898581839502056240973" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.001") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0") - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("8.999") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1101418160497943759027" - ); - // price update - assert.equal( - await ctx.DODO.methods.getMidPrice().call(), - "102353368821735563400" - ); - }); - - it("buy when R is ABOVE ONE", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("130"), "0x"), ctx.sendParam(trader), "buy when R is ABOVE ONE") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("12") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "794367183433412077653" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.002") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0") - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("7.998") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1205632816566587922347" - ); - }); - - it("sell when R is ABOVE ONE", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("0.5"), decimalStr("40"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("10.5") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "949280846351657143136" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.001") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "50851561534203512" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("9.499") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1050668302086808653352" - ); - }); - - it("sell when R is ABOVE ONE and RStatus back to ONE", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.sellBaseToken("1003002430889317763", decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE and RStatus back to ONE") - // R status - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - "9996997569110682237" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "999695745518506168723" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.001") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "101418160497943759" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - "10002002430889317763" - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1000202836320995887518" - ); - // target status - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "10002002430889317763" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1000202836320995887518" - ); - }); - - it("sell when R is ABOVE ONE and RStatus becomes BELOW ONE", async () => { - await ctx.DODO.methods.buyBaseToken(decimalStr("1"), decimalStr("110"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("2"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is ABOVE ONE and RStatus becomes BELOW ONE [gas cost worst case]") - // R status - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "2"); - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("9") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1098020621600061709144" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.001") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "200038898794388634" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("10.999") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "901779339501143902222" - ); - // target status - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "10002002430889317763" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1000400077797588777268" - ); - }); - }); - - describe("R goes below ONE", () => { - it("sell when R equals ONE", async () => { - await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell base token when balanced") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("9") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1098617454226610630663" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - "0" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "98914196817061816" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("11") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "901283631576572307521" - ); - // price update - assert.equal( - await ctx.DODO.methods.getMidPrice().call(), - "97736983274307939149" - ); - }); - - it("sell when R is BELOW ONE", async () => { - await ctx.DODO.methods.sellBaseToken(decimalStr("3"), decimalStr("90"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.sellBaseToken(decimalStr("3"), decimalStr("90"), "0x"), ctx.sendParam(trader), "sell when R is BELOW ONE") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("4") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1535961012052716726151" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - "0" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "537573733252474148" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("16") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "463501414214030799701" - ); - }); - - it("buy when R is BELOW ONE", async () => { - await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("0.5"), decimalStr("60"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE") - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("9.5") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1049294316148665165453" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.0005") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "98914196817061816" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("10.4995") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "950606769654517772731" - ); - }); - - it("buy when R is BELOW ONE and RStatus back to ONE", async () => { - await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.buyBaseToken("997008973080757728", decimalStr("110"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE and RStatus back to ONE") - // R status - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - "9997008973080757728" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "999703024198699411500" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - "997008973080757" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "98914196817061816" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - "10001994017946161515" - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1000198061604483526684" - ); - // target status - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "10001994017946161515" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1000198061604483526684" - ); - }); - - it("buy when R is BELOW ONE and RStatus becomes ABOVE ONE", async () => { - await ctx.DODO.methods.sellBaseToken(decimalStr("1"), decimalStr("90"), "0x").send(ctx.sendParam(trader)) - await logGas(ctx.DODO.methods.buyBaseToken(decimalStr("2"), decimalStr("220"), "0x"), ctx.sendParam(trader), "buy when R is BELOW ONE and RStatus becomes ABOVE ONE [gas cost worst case]") - // R status - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "1"); - // trader balances - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("11") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "897977789597854403796" - ); - // maintainer balances - assert.equal( - await ctx.BASE.methods.balanceOf(ctx.Maintainer).call(), - decimalStr("0.002") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(ctx.Maintainer).call(), - "98914196817061816" - ); - // dodo balances - assert.equal( - await ctx.DODO.methods._BASE_BALANCE_().call(), - decimalStr("8.998") - ); - assert.equal( - await ctx.DODO.methods._QUOTE_BALANCE_().call(), - "1101923296205328534388" - ); - // target status - assert.equal( - await ctx.DODO.methods._TARGET_BASE_TOKEN_AMOUNT_().call(), - "10004000000000000000" - ); - assert.equal( - await ctx.DODO.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call(), - "1000198061604483526684" - ); - }); - }); - - describe("Corner cases", () => { - it("buy or sell 0", async () => { - await ctx.DODO.methods - .sellBaseToken(decimalStr("0"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("10") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - decimalStr("1000") - ); - - await ctx.DODO.methods - .buyBaseToken(decimalStr("0"), decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - decimalStr("10") - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - decimalStr("1000") - ); - }); - - it("buy or sell a tiny amount", async () => { - // no precision problem - await ctx.DODO.methods - .sellBaseToken("1", decimalStr("0"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - "9999999999999999999" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1000000000000000000100" - ); - - // have precision problem, charge 0 - await ctx.DODO.methods - .buyBaseToken("1", decimalStr("1"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - "10000000000000000000" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1000000000000000000100" - ); - assert.equal(await ctx.DODO.methods._R_STATUS_().call(), "0"); - - // no precision problem if trading amount is extremely small - await ctx.DODO.methods - .buyBaseToken("10", decimalStr("1"), "0x") - .send(ctx.sendParam(trader)); - assert.equal( - await ctx.BASE.methods.balanceOf(trader).call(), - "10000000000000000010" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "999999999999999999100" - ); - }); - - it("sell a huge amount of base token", async () => { - await ctx.mintTestToken(trader, decimalStr("10000"), "0"); - await ctx.DODO.methods - .sellBaseToken(decimalStr("10000"), "0", "0x") - .send(ctx.sendParam(trader)); - // nearly drain out quote pool - // because the fee donated is greater than remaining quote pool - // quote lp earn a considerable profit - assert.equal( - await ctx.QUOTE.methods.balanceOf(trader).call(), - "1996900220185135480813" - ); - assert.equal( - await ctx.DODO.methods.getLpQuoteBalance(lp).call(), - "4574057156329524019750" - ); - }); - }); - - describe("Revert cases", () => { - it("price limit", async () => { - await assert.rejects( - ctx.DODO.methods - .buyBaseToken(decimalStr("1"), decimalStr("100"), "0x") - .send(ctx.sendParam(trader)), - /BUY_BASE_COST_TOO_MUCH/ - ); - await assert.rejects( - ctx.DODO.methods - .sellBaseToken(decimalStr("1"), decimalStr("100"), "0x") - .send(ctx.sendParam(trader)), - /SELL_BASE_RECEIVE_NOT_ENOUGH/ - ); - }); - - it("base balance limit", async () => { - await assert.rejects( - ctx.DODO.methods - .buyBaseToken(decimalStr("11"), decimalStr("10000"), "0x") - .send(ctx.sendParam(trader)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - - await ctx.DODO.methods - .buyBaseToken(decimalStr("1"), decimalStr("200"), "0x") - .send(ctx.sendParam(trader)); - - await assert.rejects( - ctx.DODO.methods - .buyBaseToken(decimalStr("11"), decimalStr("10000"), "0x") - .send(ctx.sendParam(trader)), - /DODO_BASE_BALANCE_NOT_ENOUGH/ - ); - }); - }); -}); diff --git a/test/V1/UniswapArbitrageur.test.ts b/test/V1/UniswapArbitrageur.test.ts deleted file mode 100644 index 19e2ffe..0000000 --- a/test/V1/UniswapArbitrageur.test.ts +++ /dev/null @@ -1,202 +0,0 @@ -/* - - Copyright 2020 DODO ZOO. - SPDX-License-Identifier: Apache-2.0 - -*/ - -import * as assert from 'assert'; -import { Contract } from 'web3-eth-contract'; - -import { DODOContext, getDODOContext } from './utils/DVMContext'; -import { - newContract, - UNISWAP_ARBITRAGEUR_CONTRACT_NAME, - UNISWAP_CONTRACT_NAME, -} from './utils/Contracts'; -import { decimalStr } from './utils/Converter'; -import { logGas } from './utils/Log'; - -let lp: string; -let keeper: string; - -let Uniswap: Contract; -let UniswapArbitrageur: Contract; - -let UniswapReverse: Contract; -let UniswapArbitrageurReverse: Contract; - -async function init(ctx: DODOContext): Promise { - await ctx.setOraclePrice(decimalStr("100")); - - lp = ctx.spareAccounts[0]; - keeper = ctx.spareAccounts[1]; - await ctx.approveDODO(lp); - - await ctx.mintTestToken(lp, decimalStr("100"), decimalStr("10000")); - - await ctx.DODO.methods.depositBase(decimalStr("10")).send(ctx.sendParam(lp)); - await ctx.DODO.methods - .depositQuote(decimalStr("1000")) - .send(ctx.sendParam(lp)); - - Uniswap = await newContract(UNISWAP_CONTRACT_NAME); - Uniswap.methods - .initialize(ctx.BASE.options.address, ctx.QUOTE.options.address) - .send(ctx.sendParam(ctx.Deployer)); - ctx.BASE.methods - .transfer(Uniswap.options.address, decimalStr("10")) - .send(ctx.sendParam(lp)); - ctx.QUOTE.methods - .transfer(Uniswap.options.address, decimalStr("2000")) - .send(ctx.sendParam(lp)); - Uniswap.methods.sync().send(ctx.sendParam(lp)); - - UniswapArbitrageur = await newContract(UNISWAP_ARBITRAGEUR_CONTRACT_NAME, [ - Uniswap.options.address, - ctx.DODO.options.address, - ]); - - UniswapReverse = await newContract(UNISWAP_CONTRACT_NAME); - UniswapReverse.methods - .initialize(ctx.BASE.options.address, ctx.QUOTE.options.address) - .send(ctx.sendParam(ctx.Deployer)); - ctx.BASE.methods - .transfer(UniswapReverse.options.address, decimalStr("10")) - .send(ctx.sendParam(lp)); - ctx.QUOTE.methods - .transfer(UniswapReverse.options.address, decimalStr("2000")) - .send(ctx.sendParam(lp)); - UniswapReverse.methods.sync().send(ctx.sendParam(lp)); - - UniswapArbitrageurReverse = await newContract( - UNISWAP_ARBITRAGEUR_CONTRACT_NAME, - [UniswapReverse.options.address, ctx.DODO.options.address] - ); -} - -describe("Uniswap Arbitrageur", () => { - let snapshotId: string; - let ctx: DODOContext; - - before(async () => { - ctx = await getDODOContext(); - await init(ctx); - }); - - beforeEach(async () => { - snapshotId = await ctx.EVM.snapshot(); - }); - - afterEach(async () => { - await ctx.EVM.reset(snapshotId); - }); - - describe("arbitrage with not reverse pair", () => { - it("buy at dodo", async () => { - await ctx.setOraclePrice(decimalStr("100")); - // dodo price 100 uniswap price 200 - // buy at dodo -<<<<<<< Updated upstream - await logGas( - UniswapArbitrageur.methods.executeBuyArbitrage(decimalStr("1")), - ctx.sendParam(keeper), - "arbitrage buy at dodo not reverse" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(keeper).call(), - "79836384956601695518" - ); - }); -======= - logGas(await UniswapArbitrageur.methods.executeBuyArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage buy at dodo not reverse") - assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518") - }) ->>>>>>> Stashed changes - - it("sell at dodo", async () => { - await ctx.setOraclePrice(decimalStr("300")); - // dodo price 300 uniswap price 200 - // sell at dodo -<<<<<<< Updated upstream - await logGas( - UniswapArbitrageur.methods.executeSellArbitrage(decimalStr("1")), - ctx.sendParam(keeper), - "arbitrage sell at dodo not reverse" - ); - assert.equal( - await ctx.BASE.methods.balanceOf(keeper).call(), - "252761069524143743" - ); - }); - }); -======= - logGas(await UniswapArbitrageur.methods.executeSellArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage sell at dodo not reverse") - assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743") - }) - }) ->>>>>>> Stashed changes - - describe("arbitrage with reverse pair", () => { - it("buy at dodo", async () => { - await ctx.setOraclePrice(decimalStr("100")); - // dodo price 100 uniswap price 200 - // buy at dodo -<<<<<<< Updated upstream - await logGas( - UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")), - ctx.sendParam(keeper), - "arbitrage buy at dodo reverse" - ); - assert.equal( - await ctx.QUOTE.methods.balanceOf(keeper).call(), - "79836384956601695518" - ); - }); -======= - logGas(await UniswapArbitrageurReverse.methods.executeBuyArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage buy at dodo reverse") - assert.equal(await ctx.QUOTE.methods.balanceOf(keeper).call(), "79836384956601695518") - }) ->>>>>>> Stashed changes - - it("sell at dodo", async () => { - await ctx.setOraclePrice(decimalStr("300")); - // dodo price 300 uniswap price 200 - // sell at dodo -<<<<<<< Updated upstream - await logGas( - UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")), - ctx.sendParam(keeper), - "arbitrage sell at dodo reverse" - ); - assert.equal( - await ctx.BASE.methods.balanceOf(keeper).call(), - "252761069524143743" - ); - }); - }); -======= - logGas(await UniswapArbitrageurReverse.methods.executeSellArbitrage(decimalStr("1")), ctx.sendParam(keeper), "arbitrage sell at dodo reverse") - assert.equal(await ctx.BASE.methods.balanceOf(keeper).call(), "252761069524143743") - }) - }) ->>>>>>> Stashed changes - - describe("revert cases", () => { - it("price not match", async () => { - await ctx.setOraclePrice(decimalStr("200")); - await assert.rejects( - UniswapArbitrageurReverse.methods - .executeBuyArbitrage(decimalStr("1")) - .send(ctx.sendParam(keeper)), - /NOT_PROFITABLE/ - ); - await assert.rejects( - UniswapArbitrageurReverse.methods - .executeSellArbitrage(decimalStr("1")) - .send(ctx.sendParam(keeper)), - /NOT_PROFITABLE/ - ); - }); - }); -}); diff --git a/test/Route/Route.test.ts b/test/V1Proxy/Route.test.ts similarity index 100% rename from test/Route/Route.test.ts rename to test/V1Proxy/Route.test.ts diff --git a/test/Proxy/proxy.classical.test.ts b/test/V2Proxy/proxy.classical.test.ts similarity index 99% rename from test/Proxy/proxy.classical.test.ts rename to test/V2Proxy/proxy.classical.test.ts index caf6cf2..a6660cd 100644 --- a/test/Proxy/proxy.classical.test.ts +++ b/test/V2Proxy/proxy.classical.test.ts @@ -119,7 +119,8 @@ async function calcRoute(ctx: ProxyContext, fromTokenAmount: string, slippage: n fromTokenAmount, toAmount, dodoPairs, - tmpDirections, + parseInt(strDirections,2), + false, deadline ) } @@ -175,7 +176,6 @@ describe("AddLiquidity", () => { await ctxV1.DODO.methods.approve(ctxV2.DODOApprove.options.address, MAX_UINT256).send(ctxV2.sendParam(trader)); await ctxV1.USDT.methods.approve(ctxV2.DODOApprove.options.address, MAX_UINT256).send(ctxV2.sendParam(trader)); await logGas(await ctxV2.DODOProxyV2.methods.addLiquidityToV1( - trader, ctxV1.DODO_USDT.options.address, decimalStr("100"), mweiStr("100"), @@ -205,7 +205,6 @@ describe("AddLiquidity", () => { console.log("weth_lp:" + weth_lp + " usdc_lp:" + usdc_lp); await ctxV1.USDC.methods.approve(ctxV2.DODOApprove.options.address, MAX_UINT256).send(ctxV2.sendParam(trader)); await logGas(await ctxV2.DODOProxyV2.methods.addLiquidityToV1( - trader, ctxV1.WETH_USDC.options.address, decimalStr("1"), mweiStr("100"), diff --git a/test/Proxy/proxy.cp.test.ts b/test/V2Proxy/proxy.cp.test.ts similarity index 98% rename from test/Proxy/proxy.cp.test.ts rename to test/V2Proxy/proxy.cp.test.ts index 9322903..e7685e6 100644 --- a/test/Proxy/proxy.cp.test.ts +++ b/test/V2Proxy/proxy.cp.test.ts @@ -140,7 +140,6 @@ describe("DODOProxyV2.0", () => { assert.equal(b_lp_2, decimalStr("0")); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer1, cp_DODO_USDT, mweiStr("50"), 0, @@ -148,7 +147,6 @@ describe("DODOProxyV2.0", () => { ), ctx.sendParam(buyer1), "bid"); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer2, cp_DODO_USDT, mweiStr("80"), 0, @@ -156,7 +154,6 @@ describe("DODOProxyV2.0", () => { ), ctx.sendParam(buyer2), "bid"); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer2, cp_DODO_USDT, mweiStr("80"), 0, @@ -164,7 +161,6 @@ describe("DODOProxyV2.0", () => { ), ctx.sendParam(buyer2), "bid"); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer2, cp_DODO_USDT, mweiStr("80"), 0, @@ -193,7 +189,6 @@ describe("DODOProxyV2.0", () => { assert.equal(b_lp_2, decimalStr("0")); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer1, cp_DODO_WETH, decimalStr("2"), 1, @@ -201,7 +196,6 @@ describe("DODOProxyV2.0", () => { ), ctx.sendParam(buyer1, "2"), "bid"); await logGas(await ctx.DODOProxyV2.methods.bid( - buyer2, cp_DODO_WETH, decimalStr("1"), 1, diff --git a/test/Proxy/proxy.dpp.test.ts b/test/V2Proxy/proxy.dpp.test.ts similarity index 99% rename from test/Proxy/proxy.dpp.test.ts rename to test/V2Proxy/proxy.dpp.test.ts index 776b391..23ebe58 100644 --- a/test/Proxy/proxy.dpp.test.ts +++ b/test/V2Proxy/proxy.dpp.test.ts @@ -236,13 +236,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 0 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.USDT.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - one jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -252,13 +252,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_USDT, "99749900"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.USDT.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - one jump second"); }); @@ -273,13 +273,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -289,13 +289,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_WETH, "165350643050738035"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump second"); }); @@ -310,11 +310,11 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2ETHToToken( - trader, ctx.DODO.options.address, 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader, "1"), "swap - two jump - inETH first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -325,11 +325,11 @@ describe("DODOProxyV2.0", () => { // console.log("b_ETH:" + b_ETH + " a_ETH:" + a_ETH); assert.equal(a_DOOD, "2908497423869401229986"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2ETHToToken( - trader, ctx.DODO.options.address, 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader, "1"), "swap - two jump - inETH second"); }); @@ -346,12 +346,12 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 var tx = await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToETH( - trader, ctx.DODO.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump - outETH - first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -366,12 +366,12 @@ describe("DODOProxyV2.0", () => { "165350643050738035" ) await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToETH( - trader, ctx.DODO.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump - outETH - second"); }); @@ -388,13 +388,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 4 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - three jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -404,13 +404,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_WETH, "165004688801375425"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - three jump second"); }); diff --git a/test/Proxy/proxy.dvm.test.ts b/test/V2Proxy/proxy.dvm.test.ts similarity index 98% rename from test/Proxy/proxy.dvm.test.ts rename to test/V2Proxy/proxy.dvm.test.ts index fa6aec1..ef5f2e6 100644 --- a/test/Proxy/proxy.dvm.test.ts +++ b/test/V2Proxy/proxy.dvm.test.ts @@ -45,7 +45,6 @@ async function init(ctx: ProxyContext): Promise { async function initCreateDVM(ctx: ProxyContext, token0: string, token1: string, token0Amount: string, token1Amount: string, ethValue: string, i: string): Promise { let PROXY = ctx.DODOProxyV2; await PROXY.methods.createDODOVendingMachine( - project, token0, token1, token0Amount, @@ -109,7 +108,6 @@ describe("DODOProxyV2.0", () => { var baseAmount = decimalStr("10000"); var quoteAmount = mweiStr("10000"); await logGas(await ctx.DODOProxyV2.methods.createDODOVendingMachine( - project, baseToken, quoteToken, baseAmount, @@ -137,7 +135,6 @@ describe("DODOProxyV2.0", () => { // var baseAmount = decimalStr("5"); // var quoteAmount = mweiStr("10000"); // await logGas(await ctx.DODOProxyV2.methods.createDODOVendingMachine( - // project, // baseToken, // quoteToken, // baseAmount, @@ -168,7 +165,6 @@ describe("DODOProxyV2.0", () => { assert.equal(b_dlp, decimalStr("0")); await logGas(await ctx.DODOProxyV2.methods.addDVMLiquidity( dvm_DODO_USDT, - lp, decimalStr("1000"), mweiStr("300"), decimalStr("0"), @@ -194,7 +190,6 @@ describe("DODOProxyV2.0", () => { assert.equal(b_dlp, decimalStr("0")); await logGas(await ctx.DODOProxyV2.methods.addDVMLiquidity( dvm_WETH_USDT, - lp, decimalStr("1"), mweiStr("6000"), decimalStr("0"), @@ -284,13 +279,13 @@ describe("DODOProxyV2.0", () => { var directions = 0 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.USDT.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - one jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -300,13 +295,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_USDT, "126151370"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.USDT.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - one jump second"); }); @@ -322,13 +317,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -338,13 +333,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_WETH, "163816613646287588"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump second"); }); @@ -359,11 +354,11 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2ETHToToken( - trader, ctx.DODO.options.address, 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader, "1"), "swap - two jump - inETH - first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -374,11 +369,11 @@ describe("DODOProxyV2.0", () => { // console.log("b_ETH:" + b_ETH + " a_ETH:" + a_ETH); assert.equal(a_DOOD, "2814340111190341070680"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2ETHToToken( - trader, ctx.DODO.options.address, 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader, "1"), "swap - two jump - inETH - second"); }); @@ -392,12 +387,12 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 var tx = await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToETH( - trader, ctx.DODO.options.address, decimalStr("1000"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump - outETH first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -407,12 +402,12 @@ describe("DODOProxyV2.0", () => { "323865907568573497" ) await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToETH( - trader, ctx.DODO.options.address, decimalStr("1000"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump - outETH second"); }); @@ -426,13 +421,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 4 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - three jump first"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -440,13 +435,13 @@ describe("DODOProxyV2.0", () => { assert.equal(a_DOOD, decimalStr("500")); assert.equal(a_WETH, "163633965833613187"); await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - three jump second"); }); diff --git a/test/V2Proxy/proxy.incentive.test.ts b/test/V2Proxy/proxy.incentive.test.ts new file mode 100644 index 0000000..696d2a8 --- /dev/null +++ b/test/V2Proxy/proxy.incentive.test.ts @@ -0,0 +1,264 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +import { decimalStr, mweiStr } from '../utils/Converter'; +import { logGas } from '../utils/Log'; +import { ProxyContext, getProxyContext } from '../utils/ProxyContextV2'; +import { assert } from 'chai'; +import * as contracts from '../utils/Contracts'; + +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.mintTestToken(lp, ctx.DODO, decimalStr("1000000")); + await ctx.mintTestToken(project, ctx.DODO, decimalStr("1000000")); + + await ctx.mintTestToken(lp, ctx.USDT, mweiStr("1000000")); + await ctx.mintTestToken(project, ctx.USDT, mweiStr("1000000")); + + await ctx.approveProxy(lp); + await ctx.approveProxy(project); + await ctx.approveProxy(trader); +} + + +async function initCreateDPP(ctx: ProxyContext, token0: string, token1: string, token0Amount: string, token1Amount: string, ethValue: string, i: string): Promise { + let PROXY = ctx.DODOProxyV2; + await PROXY.methods.createDODOPrivatePool( + token0, + token1, + token0Amount, + token1Amount, + config.lpFeeRate, + i, + config.k, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ).send(ctx.sendParam(project, ethValue)); + if (token0 == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') token0 = ctx.WETH.options.address; + if (token1 == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') token1 = ctx.WETH.options.address; + var addr = await ctx.DPPFactory.methods._REGISTRY_(token0, token1, 0).call(); + return addr; +} + +async function initCreateDVM(ctx: ProxyContext, token0: string, token1: string, token0Amount: string, token1Amount: string, ethValue: string, i: string): Promise { + let PROXY = ctx.DODOProxyV2; + await PROXY.methods.createDODOVendingMachine( + token0, + token1, + token0Amount, + token1Amount, + config.lpFeeRate, + i, + config.k, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ).send(ctx.sendParam(project, ethValue)); + if (token0 == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') token0 = ctx.WETH.options.address; + if (token1 == '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') token1 = ctx.WETH.options.address; + var addr = await ctx.DVMFactory.methods._REGISTRY_(token0, token1, 0).call(); + return addr; +} + +async function initIncentive(ctx: ProxyContext): Promise { + var blockNum = await ctx.Web3.eth.getBlockNumber(); + await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer)); + await ctx.mintTestToken(ctx.DODOIncentive.options.address, ctx.DODO, decimalStr("1000000")); +} + + +describe("DODOProxyV2.0", () => { + let snapshotId: string; + let ctx: ProxyContext; + let dpp_DODO_USDT: string; + let dvm_WETH_USDT: string; + + before(async () => { + let ETH = await contracts.newContract( + contracts.WETH_CONTRACT_NAME + ); + ctx = await getProxyContext(ETH.options.address); + await init(ctx); + dpp_DODO_USDT = await initCreateDPP(ctx, ctx.DODO.options.address, ctx.USDT.options.address, decimalStr("100000"), mweiStr("20000"), "0", mweiStr("0.2")); + dvm_WETH_USDT = await initCreateDVM(ctx, '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', ctx.USDT.options.address, decimalStr("5"), mweiStr("3000"), "5", mweiStr("600")); + console.log("dpp_DODO_USDT:", dpp_DODO_USDT); + console.log("dvm_WETH_USDT:", dvm_WETH_USDT); + await initIncentive(ctx); + }); + + beforeEach(async () => { + snapshotId = await ctx.EVM.snapshot(); + }); + + afterEach(async () => { + await ctx.EVM.reset(snapshotId); + }); + + describe("DODOIncentive", () => { + + it("incentive-switch with trade", async () => { + await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); + var totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + var blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("Init - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + + //Aim to increase block + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("Close BlockNumber:", blockNum + 1) + await ctx.DODOIncentive.methods.switchIncentive(0).send(ctx.sendParam(ctx.Deployer)); + totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("Close incentive - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + + //Aim to increase block + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + + blockNum = await ctx.Web3.eth.getBlockNumber(); + await ctx.DODOIncentive.methods.switchIncentive(blockNum + 1).send(ctx.sendParam(ctx.Deployer)); + console.log("Open BlockNumber:", blockNum + 1) + //Aim to increase block + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); + totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("End incentive - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + assert(totalReward, decimalStr("100")); + }); + + it("incentive-changeBoost with trade", async () => { + await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); + var totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + var totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + var blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("Init - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + + //Aim to increase block + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("Change BlockNumber:", blockNum + 1) + await ctx.DODOIncentive.methods.changePerReward(decimalStr("20")).send(ctx.sendParam(ctx.Deployer)); + totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("change incentive - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + + //Aim to increase block + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.mintTestToken(lp, ctx.DODO, decimalStr("1000")); + await ctx.DODOIncentive.methods.changePerReward(decimalStr("10")).send(ctx.sendParam(ctx.Deployer)); + totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + blockNum = await ctx.Web3.eth.getBlockNumber(); + console.log("End incentive - Total Reward:" + totalReward + "; Total distribution:" + totalDistribution + "; BlockNumber:" + blockNum); + + assert(totalReward, decimalStr("140")); + }); + + it("tigger - incentive", async () => { + await ctx.mintTestToken(trader, ctx.DODO, decimalStr("2000")); + var b_DODO = await ctx.DODO.methods.balanceOf(trader).call() + var b_USDT = await ctx.USDT.methods.balanceOf(trader).call() + console.log("Before DODO:" + b_DODO + "; USDT:" + b_USDT); + + var b_totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + var b_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + console.log("Before Total Reward:" + b_totalReward + "; Total distribution:" + b_totalDistribution) + + var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() + var a_USDT = await ctx.USDT.methods.balanceOf(trader).call() + console.log("After No Incentive DODO:" + a_DODO + "; USDT:" + a_USDT); + + var dodoPairs = [ + dpp_DODO_USDT + ] + var directions = 0 + + + await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( + ctx.DODO.options.address, + ctx.USDT.options.address, + decimalStr("500"), + 1, + dodoPairs, + directions, + false, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ), ctx.sendParam(trader), "swap without incentive first"); + + await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( + ctx.DODO.options.address, + ctx.USDT.options.address, + decimalStr("500"), + 1, + dodoPairs, + directions, + false, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ), ctx.sendParam(trader), "swap without incentive second"); + + var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() + var a_USDT = await ctx.USDT.methods.balanceOf(trader).call() + console.log("After No Incentive DODO:" + a_DODO + "; USDT:" + a_USDT); + + await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( + ctx.DODO.options.address, + ctx.USDT.options.address, + decimalStr("500"), + 1, + dodoPairs, + directions, + true, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ), ctx.sendParam(trader), "swap with incentive first"); + + await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( + ctx.DODO.options.address, + ctx.USDT.options.address, + decimalStr("500"), + 1, + dodoPairs, + directions, + true, + Math.floor(new Date().getTime() / 1000 + 60 * 10) + ), ctx.sendParam(trader), "swap with incentive second"); + + var a_totalReward = await ctx.DODOIncentive.methods.totalReward().call(); + var a_totalDistribution = await ctx.DODOIncentive.methods.totalDistribution().call(); + console.log("After Total Reward:" + a_totalReward + "; Total distribution:" + a_totalDistribution) + + a_DODO = await ctx.DODO.methods.balanceOf(trader).call() + a_USDT = await ctx.USDT.methods.balanceOf(trader).call() + console.log("After Incentive DODO:" + a_DODO + "; USDT:" + a_USDT); + assert(a_DODO, "1095000000000000000"); + }); + }); +}); diff --git a/test/Proxy/proxy.mix.test.ts b/test/V2Proxy/proxy.mix.test.ts similarity index 98% rename from test/Proxy/proxy.mix.test.ts rename to test/V2Proxy/proxy.mix.test.ts index df6e1a7..94fa6b3 100644 --- a/test/Proxy/proxy.mix.test.ts +++ b/test/V2Proxy/proxy.mix.test.ts @@ -60,7 +60,6 @@ async function initCreateDPP(ctx: ProxyContext, token0: string, token1: string, async function initCreateDVM(ctx: ProxyContext, token0: string, token1: string, token0Amount: string, token1Amount: string, ethValue: string, i: string): Promise { let PROXY = ctx.DODOProxyV2; await PROXY.methods.createDODOVendingMachine( - project, token0, token1, token0Amount, @@ -114,13 +113,13 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToToken( - trader, ctx.DODO.options.address, ctx.WETH.options.address, decimalStr("500"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -141,11 +140,11 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2ETHToToken( - trader, ctx.DODO.options.address, 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader, "1"), "swap - two jump - inETH"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); @@ -169,12 +168,12 @@ describe("DODOProxyV2.0", () => { ] var directions = 2 var tx = await logGas(await ctx.DODOProxyV2.methods.dodoSwapV2TokenToETH( - trader, ctx.DODO.options.address, decimalStr("10000"), 1, dodoPairs, directions, + false, Math.floor(new Date().getTime() / 1000 + 60 * 10) ), ctx.sendParam(trader), "swap - two jump - outETH"); var a_DOOD = await ctx.DODO.methods.balanceOf(trader).call(); diff --git a/test/utils-v1/ProxyContextV1.ts b/test/utils-v1/ProxyContextV1.ts index 55199cb..99b1c40 100644 --- a/test/utils-v1/ProxyContextV1.ts +++ b/test/utils-v1/ProxyContextV1.ts @@ -256,7 +256,7 @@ export class DODOContext { await this.DODOV1Proxy02.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer)); await this.DODOIncentive.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer)); - await this.DODOApprove.methods.init(this.Deployer,this.DODOV1Proxy02.options.address).send(this.sendParam(this.Deployer)); + await this.DODOApprove.methods.init(this.Deployer, this.DODOV1Proxy01.options.address).send(this.sendParam(this.Deployer)); await this.DODOIncentive.methods.changeDODOProxy(this.DODOV1Proxy02.options.address).send(this.sendParam(this.Deployer)); this.DODOSwapCalcHelper = await contracts.newContract( diff --git a/test/utils/Contracts.ts b/test/utils/Contracts.ts index 42cc308..f5bd3e0 100644 --- a/test/utils/Contracts.ts +++ b/test/utils/Contracts.ts @@ -45,6 +45,7 @@ export const DPP_ADMIN_NAME = "DPPAdmin" export const DODO_CALLEE_HELPER_NAME = "DODOCalleeHelper" export const CROWD_POOLING_NAME = "CP" export const CROWD_POOLING_FACTORY = "CrowdPoolingFactory" +export const DODO_INCENTIVE = "DODOIncentive" interface ContractJson { abi: any; diff --git a/test/utils/CrowdPoolingContext.ts b/test/utils/CrowdPoolingContext.ts index c8710a9..4be9af2 100644 --- a/test/utils/CrowdPoolingContext.ts +++ b/test/utils/CrowdPoolingContext.ts @@ -30,6 +30,7 @@ export interface CPContextInitConfig { freezeDuration: BigNumber; vestingDuration: BigNumber; cliffRate: string; + quoteTokenContract: string; } @@ -43,6 +44,7 @@ export class CPContext { Deployer: string; Maintainer: string; SpareAccounts: string[]; + DODOCallee: Contract; constructor() { } @@ -67,10 +69,18 @@ export class CPContext { contracts.MINTABLE_ERC20_CONTRACT_NAME, ["TestBase", "BASE", 18] ); - this.QUOTE = await contracts.newContract( - contracts.MINTABLE_ERC20_CONTRACT_NAME, - ["TestQuote", "QUOTE", 18] - ); + if(config.quoteTokenContract){ + this.QUOTE = await contracts.newContract( + config.quoteTokenContract, + ["TestQuote", "QUOTE", 18] + ); + }else{ + this.QUOTE = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["TestQuote", "QUOTE", 18] + ); + } + this.DODOCallee = await contracts.newContract(contracts.DODO_CALLEE_HELPER_NAME,[this.QUOTE.options.address]); this.DVMFactory = await contracts.newContract(contracts.DVM_FACTORY_NAME, [ diff --git a/test/utils/Log.ts b/test/utils/Log.ts index 7e7c3b7..2ad8f6c 100644 --- a/test/utils/Log.ts +++ b/test/utils/Log.ts @@ -13,6 +13,7 @@ export const numberWithCommas = x => x.toString().replace(/\B(?=(\d{3})+(?!\d))/ export async function logGas(funcCall: any, params: any, desc: string) { const estimatedGas = await funcCall.estimateGas(params) + const receipt = await funcCall.send(params) const gasUsed = receipt.gasUsed; let colorFn; @@ -27,4 +28,4 @@ export async function logGas(funcCall: any, params: any, desc: string) { console.log(("Gas estimated:" + numberWithCommas(estimatedGas)).padEnd(60, '.'), blueText(desc) + " ", colorFn(numberWithCommas(gasUsed).padStart(5))); return receipt -} \ No newline at end of file +} diff --git a/test/utils/ProxyContextV2.ts b/test/utils/ProxyContextV2.ts index a8444d3..b2d178a 100644 --- a/test/utils/ProxyContextV2.ts +++ b/test/utils/ProxyContextV2.ts @@ -37,6 +37,9 @@ export class ProxyContext { USDT: Contract; WETH: Contract; + //Functions + DODOIncentive: Contract; + Deployer: string; Maintainer: string; SpareAccounts: string[]; @@ -53,6 +56,19 @@ export class ProxyContext { this.WETH = contracts.getContractWithAddress(contracts.WETH_CONTRACT_NAME, weth); + 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.USDC = await contracts.newContract( + contracts.MINTABLE_ERC20_CONTRACT_NAME, + ["USDC Token", "USDC", 6] + ); + var cloneFactory = await contracts.newContract( contracts.CLONE_FACTORY_CONTRACT_NAME ); @@ -78,6 +94,11 @@ export class ProxyContext { contracts.SMART_APPROVE ); + //DODO Incentive + this.DODOIncentive = await contracts.newContract( + contracts.DODO_INCENTIVE, + [this.DODO.options.address] + ) this.DPPFactory = await contracts.newContract(contracts.DPP_FACTORY_NAME, [ @@ -112,25 +133,17 @@ export class ProxyContext { this.CPFactory.options.address, this.WETH.options.address, this.DODOApprove.options.address, - this.DODOSellHelper.options.address + this.DODOSellHelper.options.address, + "0x0000000000000000000000000000000000000000", + this.DODOIncentive.options.address ] ); await this.DODOProxyV2.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer)); await this.DODOApprove.methods.init(this.Deployer,this.DODOProxyV2.options.address).send(this.sendParam(this.Deployer)); - - 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.USDC = await contracts.newContract( - contracts.MINTABLE_ERC20_CONTRACT_NAME, - ["USDC Token", "USDC", 6] - ); + await this.DODOIncentive.methods.initOwner(this.Deployer).send(this.sendParam(this.Deployer)); + + await this.DODOIncentive.methods.changeDODOProxy(this.DODOProxyV2.options.address).send(this.sendParam(this.Deployer)); this.DODOCalleeHelper = await contracts.newContract( contracts.DODO_CALLEE_HELPER_NAME, diff --git a/truffle-config.js b/truffle-config.js index 97f64a2..2da79dd 100644 --- a/truffle-config.js +++ b/truffle-config.js @@ -43,7 +43,6 @@ module.exports = { MOCK_TOKEN: false, MOCK_V2_POOL: false, MOCK_V2_SWAP: false, - HELPER_V2: false, MANUAL_ADD_POOL: false }, diff --git a/truffle-test.sh b/truffle-test.sh index 7783009..0f64f7d 100644 --- a/truffle-test.sh +++ b/truffle-test.sh @@ -3,35 +3,40 @@ truffle compile --all if [ "$1"x = "proxy-dpp"x ] then - truffle test ./test/Proxy/proxy.dpp.test.ts + truffle test ./test/V2Proxy/proxy.dpp.test.ts fi if [ "$1"x = "proxy-dvm"x ] then - truffle test ./test/Proxy/proxy.dvm.test.ts + truffle test ./test/V2Proxy/proxy.dvm.test.ts fi if [ "$1"x = "proxy-mix"x ] then - truffle test ./test/Proxy/proxy.mix.test.ts + truffle test ./test/V2Proxy/proxy.mix.test.ts fi if [ "$1"x = "proxy-classical"x ] then - truffle test ./test/Proxy/proxy.classical.test.ts + truffle test ./test/V2Proxy/proxy.classical.test.ts fi if [ "$1"x = "proxy-cp"x ] then - truffle test ./test/Proxy/proxy.cp.test.ts + truffle test ./test/V2Proxy/proxy.cp.test.ts fi -if [ "$1"x = "route-incentive"x ] +if [ "$1"x = "proxy-incentive"x ] then - truffle test ./test/Route/Incentive.test.ts + truffle test ./test/V2Proxy/proxy.incentive.test.ts fi -if [ "$1"x = "route"x ] -then - truffle test ./test/Route/route.test.ts -fi \ No newline at end of file +# if [ "$1"x = "route-incentive"x ] +# then +# truffle test ./test/Route/Incentive.test.ts +# fi + +# if [ "$1"x = "route"x ] +# then +# truffle test ./test/Route/route.test.ts +# fi \ No newline at end of file