From e7923043587110a953dbcbc4ea6622324cc8c6f6 Mon Sep 17 00:00:00 2001 From: owen05 Date: Wed, 11 Nov 2020 17:13:46 +0800 Subject: [PATCH] dodo route logic fix --- contracts/SmartRoute/SmartSwap.sol | 57 ++++--- contracts/helper/DODOSellHelper.sol | 226 ++++++++++++++++++++++++++++ contracts/intf/IDODO.sol | 81 ++++++++++ contracts/intf/IDODOSellHelper.sol | 14 ++ test/Route/Route.test.ts | 111 ++++---------- test/utils-v1/Context-route.ts | 8 +- test/utils-v1/Contracts.ts | 3 + 7 files changed, 388 insertions(+), 112 deletions(-) create mode 100644 contracts/helper/DODOSellHelper.sol create mode 100644 contracts/intf/IDODO.sol create mode 100644 contracts/intf/IDODOSellHelper.sol diff --git a/contracts/SmartRoute/SmartSwap.sol b/contracts/SmartRoute/SmartSwap.sol index aba2dde..a501ea2 100644 --- a/contracts/SmartRoute/SmartSwap.sol +++ b/contracts/SmartRoute/SmartSwap.sol @@ -12,8 +12,9 @@ import {ExternalCall} from "../lib/ExternalCall.sol"; import {IERC20} from "../intf/IERC20.sol"; import {UniversalERC20} from "../lib/UniversalERC20.sol"; import {SafeMath} from "../lib/SafeMath.sol"; -import {DecimalMath} from "../lib/DecimalMath.sol"; +import {IDODOSellHelper} from "../intf/IDODOSellHelper.sol"; import {ISmartApprove} from "../intf/ISmartApprove.sol"; +import {IDODO} from "../intf/IDODO.sol"; contract SmartSwap is Ownable { @@ -21,11 +22,11 @@ contract SmartSwap is Ownable { using UniversalERC20 for IERC20; using ExternalCall for address; - ISmartApprove public smartApprove; - IERC20 constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); + ISmartApprove public smartApprove; + IDODOSellHelper public dodoSellHelper; - event Swapped( + event OrderHistory( IERC20 indexed fromToken, IERC20 indexed toToken, address indexed sender, @@ -35,8 +36,9 @@ contract SmartSwap is Ownable { event ExternalRecord(address indexed to, address indexed sender); - constructor(address _smartApprove) public { + constructor(address _smartApprove,address _dodoSellHelper) public { smartApprove = ISmartApprove(_smartApprove); + dodoSellHelper = IDODOSellHelper(_dodoSellHelper); } function dodoSwap( @@ -44,40 +46,41 @@ contract SmartSwap is Ownable { IERC20 toToken, uint256 fromTokenAmount, uint256 minReturnAmount, - address[] memory callPairs, - bytes memory callDataConcat, - uint256[] memory starts, - uint256[] memory gasLimitsAndValues + address[] memory dodoPairs, + uint256[] memory directions ) public payable returns (uint256 returnAmount) { require(minReturnAmount > 0, "Min return should be bigger then 0."); - require(callPairs.length > 0, "pairs should exists."); + require(dodoPairs.length > 0, "pairs should exists."); if (fromToken != ETH_ADDRESS) { smartApprove.claimTokens(fromToken, msg.sender, address(this), fromTokenAmount); } - for (uint256 i = 0; i < callPairs.length; i++) { - require(callPairs[i] != address(smartApprove), "Access denied"); - require( - callPairs[i].externalCall( - gasLimitsAndValues[i] & ((1 << 128) - 1), - callDataConcat, - starts[i], - starts[i + 1] - starts[i], - gasLimitsAndValues[i] >> 128 - ),"Swap Transaction Error!" - ); + for (uint256 i = 0; i < dodoPairs.length; i++) { + uint256 curDirection = directions[i]; + address curDodoPair = dodoPairs[i]; + if(curDirection == 0){ + address curDodoBase = IDODO(curDodoPair)._BASE_TOKEN_(); + uint256 curAmountIn = IERC20(curDodoBase).balanceOf(address(this)); + IERC20(curDodoBase).approve(curDodoPair,curAmountIn); + IDODO(curDodoPair).sellBaseToken(curAmountIn, 0, ""); + }else { + address curDodoQuote = IDODO(curDodoPair)._QUOTE_TOKEN_(); + uint256 curAmountIn = IERC20(curDodoQuote).balanceOf(address(this)); + IERC20(curDodoQuote).approve(curDodoPair,curAmountIn); + uint256 canBuyBaseAmount = dodoSellHelper.querySellQuoteToken(curDodoPair,curAmountIn); + IDODO(curDodoPair).buyBaseToken(canBuyBaseAmount, curAmountIn, ""); + } } - fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); returnAmount = toToken.universalBalanceOf(address(this)); require(returnAmount >= minReturnAmount, "Return amount is not enough"); toToken.universalTransfer(msg.sender, returnAmount); - emit Swapped(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount); + emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount); } - //TODO:change + function externalSwap( IERC20 fromToken, IERC20 toToken, @@ -100,16 +103,12 @@ contract SmartSwap is Ownable { require(success, "Contract Swap execution Failed"); - // Return back all unswapped fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); - returnAmount = toToken.universalBalanceOf(address(this)); require(returnAmount >= minReturnAmount, "Return amount is not enough"); toToken.universalTransfer(msg.sender, returnAmount); - - emit Swapped(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount); - + emit OrderHistory(fromToken, toToken, msg.sender, fromTokenAmount, returnAmount); emit ExternalRecord(to, msg.sender); } } diff --git a/contracts/helper/DODOSellHelper.sol b/contracts/helper/DODOSellHelper.sol new file mode 100644 index 0000000..2a41e92 --- /dev/null +++ b/contracts/helper/DODOSellHelper.sol @@ -0,0 +1,226 @@ +/** + *Submitted for verification at Etherscan.io on 2020-10-10 +*/ + +// File: contracts/intf/IDODO.sol + +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +import {IDODO} from "../intf/IDODO.sol"; +import {SafeMath} from "../lib/SafeMath.sol"; +import {DecimalMath} from "../lib/DecimalMath.sol"; +// import {DODOMath} from "../lib/DODOMath.sol"; + + +library DODOMath { + using SafeMath for uint256; + + /* + Integrate dodo curve fron V1 to V2 + require V0>=V1>=V2>0 + res = (1-k)i(V1-V2)+ikV0*V0(1/V2-1/V1) + let V1-V2=delta + res = i*delta*(1-k+k(V0^2/V1/V2)) + */ + function _GeneralIntegrate( + uint256 V0, + uint256 V1, + uint256 V2, + uint256 i, + uint256 k + ) internal pure returns (uint256) { + uint256 fairAmount = DecimalMath.mul(i, V1.sub(V2)); // i*delta + uint256 V0V0V1V2 = DecimalMath.divCeil(V0.mul(V0).div(V1), V2); + uint256 penalty = DecimalMath.mul(k, V0V0V1V2); // k(V0^2/V1/V2) + return DecimalMath.mul(fairAmount, DecimalMath.ONE.sub(k).add(penalty)); + } + + /* + The same with integration expression above, we have: + i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) + Given Q1 and deltaB, solve Q2 + This is a quadratic function and the standard version is + aQ2^2 + bQ2 + c = 0, where + a=1-k + -b=(1-k)Q1-kQ0^2/Q1+i*deltaB + c=-kQ0^2 + and Q2=(-b+sqrt(b^2+4(1-k)kQ0^2))/2(1-k) + note: another root is negative, abondan + if deltaBSig=true, then Q2>Q1 + if deltaBSig=false, then Q2= kQ02Q1) { + b = b.sub(kQ02Q1); + minusbSig = true; + } else { + b = kQ02Q1.sub(b); + minusbSig = false; + } + + // calculate sqrt + uint256 squareRoot = DecimalMath.mul( + DecimalMath.ONE.sub(k).mul(4), + DecimalMath.mul(k, Q0).mul(Q0) + ); // 4(1-k)kQ0^2 + squareRoot = b.mul(b).add(squareRoot).sqrt(); // sqrt(b*b+4(1-k)kQ0*Q0) + + // final res + uint256 denominator = DecimalMath.ONE.sub(k).mul(2); // 2(1-k) + uint256 numerator; + if (minusbSig) { + numerator = b.add(squareRoot); + } else { + numerator = squareRoot.sub(b); + } + + if (deltaBSig) { + return DecimalMath.divFloor(numerator, denominator); + } else { + return DecimalMath.divCeil(numerator, denominator); + } + } + + /* + Start from the integration function + i*deltaB = (Q2-Q1)*(1-k+kQ0^2/Q1/Q2) + Assume Q2=Q0, Given Q1 and deltaB, solve Q0 + let fairAmount = i*deltaB + */ + function _SolveQuadraticFunctionForTarget( + uint256 V1, + uint256 k, + uint256 fairAmount + ) internal pure returns (uint256 V0) { + // V0 = V1+V1*(sqrt-1)/2k + uint256 sqrt = DecimalMath.divCeil(DecimalMath.mul(k, fairAmount).mul(4), V1); + sqrt = sqrt.add(DecimalMath.ONE).mul(DecimalMath.ONE).sqrt(); + uint256 premium = DecimalMath.divCeil(sqrt.sub(DecimalMath.ONE), k.mul(2)); + // V0 is greater than or equal to V1 according to the solution + return DecimalMath.mul(V1, DecimalMath.ONE.add(premium)); + } +} + + +contract DODOSellHelper { + using SafeMath for uint256; + + enum RStatus {ONE, ABOVE_ONE, BELOW_ONE} + + uint256 constant ONE = 10**18; + + struct DODOState { + uint256 oraclePrice; + uint256 K; + uint256 B; + uint256 Q; + uint256 baseTarget; + uint256 quoteTarget; + RStatus rStatus; + } + + function querySellBaseToken(address dodo, uint256 amount) public view returns (uint256) { + return IDODO(dodo).querySellBaseToken(amount); + } + + function querySellQuoteToken(address dodo, uint256 amount) public view returns (uint256) { + DODOState memory state; + (state.baseTarget, state.quoteTarget) = IDODO(dodo).getExpectedTarget(); + state.rStatus = RStatus(IDODO(dodo)._R_STATUS_()); + state.oraclePrice = IDODO(dodo).getOraclePrice(); + state.Q = IDODO(dodo)._QUOTE_BALANCE_(); + state.B = IDODO(dodo)._BASE_BALANCE_(); + state.K = IDODO(dodo)._K_(); + + uint256 boughtAmount; + // Determine the status (RStatus) and calculate the amount + // based on the state + if (state.rStatus == RStatus.ONE) { + boughtAmount = _ROneSellQuoteToken(amount, state); + } else if (state.rStatus == RStatus.ABOVE_ONE) { + boughtAmount = _RAboveSellQuoteToken(amount, state); + } else { + uint256 backOneBase = state.B.sub(state.baseTarget); + uint256 backOneQuote = state.quoteTarget.sub(state.Q); + if (amount <= backOneQuote) { + boughtAmount = _RBelowSellQuoteToken(amount, state); + } else { + boughtAmount = backOneBase.add( + _ROneSellQuoteToken(amount.sub(backOneQuote), state) + ); + } + } + // Calculate fees + return + DecimalMath.divFloor( + boughtAmount, + DecimalMath.ONE.add(IDODO(dodo)._MT_FEE_RATE_()).add(IDODO(dodo)._LP_FEE_RATE_()) + ); + } + + function _ROneSellQuoteToken(uint256 amount, DODOState memory state) + internal + pure + returns (uint256 receiveBaseToken) + { + uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); + uint256 B2 = DODOMath._SolveQuadraticFunctionForTrade( + state.baseTarget, + state.baseTarget, + DecimalMath.mul(i, amount), + false, + state.K + ); + return state.baseTarget.sub(B2); + } + + function _RAboveSellQuoteToken(uint256 amount, DODOState memory state) + internal + pure + returns (uint256 receieBaseToken) + { + uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); + uint256 B2 = DODOMath._SolveQuadraticFunctionForTrade( + state.baseTarget, + state.B, + DecimalMath.mul(i, amount), + false, + state.K + ); + return state.B.sub(B2); + } + + function _RBelowSellQuoteToken(uint256 amount, DODOState memory state) + internal + pure + returns (uint256 receiveBaseToken) + { + uint256 Q1 = state.Q.add(amount); + uint256 i = DecimalMath.divFloor(ONE, state.oraclePrice); + return DODOMath._GeneralIntegrate(state.quoteTarget, Q1, state.Q, i, state.K); + } +} \ No newline at end of file diff --git a/contracts/intf/IDODO.sol b/contracts/intf/IDODO.sol new file mode 100644 index 0000000..69d3d66 --- /dev/null +++ b/contracts/intf/IDODO.sol @@ -0,0 +1,81 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + + +interface IDODO { + function init( + address owner, + address supervisor, + address maintainer, + address baseToken, + address quoteToken, + address oracle, + uint256 lpFeeRate, + uint256 mtFeeRate, + uint256 k, + uint256 gasPriceLimit + ) external; + + function transferOwnership(address newOwner) external; + + function claimOwnership() external; + + function sellBaseToken( + uint256 amount, + uint256 minReceiveQuote, + bytes calldata data + ) external returns (uint256); + + function buyBaseToken( + uint256 amount, + uint256 maxPayQuote, + bytes calldata data + ) external returns (uint256); + + function querySellBaseToken(uint256 amount) external view returns (uint256 receiveQuote); + + function queryBuyBaseToken(uint256 amount) external view returns (uint256 payQuote); + + function depositBaseTo(address to, uint256 amount) external returns (uint256); + + function withdrawBase(uint256 amount) external returns (uint256); + + function withdrawAllBase() external returns (uint256); + + function depositQuoteTo(address to, uint256 amount) external returns (uint256); + + function withdrawQuote(uint256 amount) external returns (uint256); + + function withdrawAllQuote() external returns (uint256); + + function _BASE_CAPITAL_TOKEN_() external returns (address); + + function _QUOTE_CAPITAL_TOKEN_() external returns (address); + + function _BASE_TOKEN_() external returns (address); + + function _QUOTE_TOKEN_() external returns (address); + + function _R_STATUS_() external view returns (uint8); + + function _QUOTE_BALANCE_() external view returns (uint256); + + function _BASE_BALANCE_() external view returns (uint256); + + function _K_() external view returns (uint256); + + function _MT_FEE_RATE_() external view returns (uint256); + + function _LP_FEE_RATE_() external view returns (uint256); + + function getExpectedTarget() external view returns (uint256 baseTarget, uint256 quoteTarget); + + function getOraclePrice() external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/intf/IDODOSellHelper.sol b/contracts/intf/IDODOSellHelper.sol new file mode 100644 index 0000000..69fa9b4 --- /dev/null +++ b/contracts/intf/IDODOSellHelper.sol @@ -0,0 +1,14 @@ +/* + + Copyright 2020 DODO ZOO. + SPDX-License-Identifier: Apache-2.0 + +*/ + +pragma solidity 0.6.9; +pragma experimental ABIEncoderV2; + +interface IDODOSellHelper { + function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256); + function querySellBaseToken(address dodo, uint256 amount) external view returns (uint256); +} diff --git a/test/Route/Route.test.ts b/test/Route/Route.test.ts index 011be8d..08823c8 100644 --- a/test/Route/Route.test.ts +++ b/test/Route/Route.test.ts @@ -48,7 +48,6 @@ async function initUSDT_USDC(ctx: DODOContext): Promise { await ctx.approvePair(USDT,USDC,USDT_USDC.options.address,lp); await ctx.mintToken(USDT,USDC,lp, mweiStr("1000"), mweiStr("1000")); - await ctx.mintToken(USDT,USDC,trader, mweiStr("0"), mweiStr("0")); await USDT_USDC.methods .depositBaseTo(lp, mweiStr("1000")) @@ -58,6 +57,7 @@ async function initUSDT_USDC(ctx: DODOContext): Promise { .send(ctx.sendParam(lp)); } + async function initWETH_USDC(ctx: DODOContext): Promise { await ctx.setOraclePrice(ctx.WETH_USDC_ORACLE,mweiStr("450")); lp = ctx.spareAccounts[0]; @@ -81,77 +81,38 @@ async function initWETH_USDC(ctx: DODOContext): Promise { //mock sdk logic async function calcRoute(ctx: DODOContext,fromTokenAmount:string,slippage:number,routes:any[],pairs:any[]) { let swapAmount = fromTokenAmount + let directions:number[] = [] + let dodoPairs:string[] = [] + - let callPairs: string[] = [] - let datas: string = "" - let starts: number[] = [] - let gAndV: number[] = [] for (let i = 0; i < pairs.length; i++) { - if(i == 0){ - starts.push(0); - } let curPair = pairs[i] - let curContact =pairs[i].pairContract; - let curData = ''; - let curApproveData = ''; - + dodoPairs.push(curPair.pair) + let curContact = pairs[i].pairContract if (curPair.base === routes[i].address) { - curApproveData = await pairs[i].baseContract.methods.approve(curPair.pair,swapAmount).encodeABI() - curApproveData = curApproveData.substring(2,curApproveData.length) - datas += curApproveData - starts.push(datas.length/2) - gAndV.push(0) - callPairs.push(pairs[i].baseContract.options.address); - curData = await curContact.methods.sellBaseToken(swapAmount, 0, "0x").encodeABI() - console.log(i + ":b-for-swapAmount:",swapAmount); + directions[i] = 0; swapAmount = await curContact.methods.querySellBaseToken(swapAmount).call(); - console.log(i + ":a-for-swapAmount:",swapAmount); + console.log(i + "-swapAmount:",swapAmount); } else { - curApproveData = await pairs[i].quoteContract.methods.approve(curPair.pair,swapAmount).encodeABI() - curApproveData = curApproveData.substring(2,curApproveData.length) - datas += curApproveData - starts.push(datas.length/2) - gAndV.push(0) - callPairs.push(pairs[i].quoteContract.options.address); - console.log(i + ":b-for-swapAmount:",swapAmount); - let baseDecimal = await pairs[i].baseContract.methods.decimals().call(); - let quoteDecimal = await pairs[i].quoteContract.methods.decimals().call(); - let curPairDetail = { - B: new BigNumber(await curContact.methods._BASE_BALANCE_().call() / 10 ** baseDecimal), - Q: new BigNumber(await curContact.methods._QUOTE_BALANCE_().call() / 10 ** quoteDecimal), - B0: new BigNumber(await curContact.methods._TARGET_BASE_TOKEN_AMOUNT_().call() / 10 ** baseDecimal), - Q0: new BigNumber(await curContact.methods._TARGET_QUOTE_TOKEN_AMOUNT_().call() / 10 ** quoteDecimal), - RStatus: await curContact.methods._R_STATUS_().call(), - OraclePrice: new BigNumber(await curContact.methods.getOraclePrice().call() / 10 ** (18-baseDecimal + quoteDecimal)), - k: new BigNumber(parseInt(ctx.k) / 1e18), - mtFeeRate: new BigNumber(parseInt(ctx.mtFeeRate) / 1e18), - lpFeeRate: new BigNumber(parseInt(ctx.lpFeeRate) / 1e18) - } - let dodoHelper = new DODOHelper(curPairDetail) - //TODO:2倍? - let tmpQuoteAmount = new BigNumber(swapAmount).multipliedBy(1-0.006).toFixed(0, BigNumber.ROUND_DOWN) - let tmpBaseAmount = dodoHelper.queryBuyQuote(new BigNumber(fromWei(tmpQuoteAmount,'mwei'))).toString(); - curData = await curContact.methods.buyBaseToken(decimalStr(tmpBaseAmount), swapAmount, "0x").encodeABI() - swapAmount = decimalStr(tmpBaseAmount); - console.log(i + ":a-for-swapAmount:",swapAmount); + directions[i] = 1; + swapAmount = await ctx.DODOSellHelper.methods.querySellQuoteToken(curPair.pair,swapAmount).call(); + console.log(i + "-swapAmount:",swapAmount); } - curData = curData.substring(2,curData.length) - datas += curData - starts.push(datas.length/2) - gAndV.push(0) - callPairs.push(curPair.pair) } - datas = "0x" + datas; + let toAmount = new BigNumber(swapAmount).multipliedBy(1-slippage).toFixed(0, BigNumber.ROUND_DOWN) + + console.log("minAmount:",toAmount); + // console.log("dodoPairs",dodoPairs); + // console.log("directions",directions); + return ctx.SmartSwap.methods.dodoSwap( routes[0].address, routes[routes.length-1].address, fromTokenAmount, toAmount, - callPairs, - datas, - starts, - gAndV + dodoPairs, + directions ) } @@ -195,14 +156,12 @@ describe("Trader", () => { pair: ctx.DODO_USDT.options.address, base: ctx.DODO.options.address, /*only for test*/ - pairContract: ctx.DODO_USDT, - baseContract: ctx.DODO, - quoteContract: ctx.USDT + pairContract: ctx.DODO_USDT /**************/ }]; - var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "route swap") - // console.log(tx.events['Swapped']); + var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "directly swap") + // console.log(tx.events['OrderHistory']); var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() var a_USDT = await ctx.USDT.methods.balanceOf(trader).call() console.log("After DODO:" + fromWei(a_DODO,'ether') + "; USDT:" + fromWei(a_USDT,'mwei')); @@ -235,21 +194,17 @@ describe("Trader", () => { pair: ctx.DODO_USDT.options.address, base: ctx.DODO.options.address, /*only for test*/ - pairContract: ctx.DODO_USDT, - baseContract: ctx.DODO, - quoteContract: ctx.USDT + pairContract: ctx.DODO_USDT /**************/ },{ pair: ctx.USDT_USDC.options.address, base: ctx.USDT.options.address, /*only for test*/ - pairContract: ctx.USDT_USDC, - baseContract: ctx.USDT, - quoteContract: ctx.USDC + pairContract: ctx.USDT_USDC /**************/ }]; - var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "route swap") + var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "tow hops swap") // console.log(tx.events['Swapped']); var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() var a_USDC = await ctx.USDC.methods.balanceOf(trader).call() @@ -286,30 +241,24 @@ describe("Trader", () => { pair: ctx.DODO_USDT.options.address, base: ctx.DODO.options.address, /*only for test*/ - pairContract: ctx.DODO_USDT, - baseContract: ctx.DODO, - quoteContract: ctx.USDT + pairContract: ctx.DODO_USDT /**************/ },{ pair: ctx.USDT_USDC.options.address, base: ctx.USDT.options.address, /*only for test*/ - pairContract: ctx.USDT_USDC, - baseContract: ctx.USDT, - quoteContract: ctx.USDC + pairContract: ctx.USDT_USDC /**************/ },{ pair: ctx.WETH_USDC.options.address, base: ctx.WETH.options.address, /*only for test*/ - pairContract: ctx.WETH_USDC, - baseContract: ctx.WETH, - quoteContract: ctx.USDC + pairContract: ctx.WETH_USDC /**************/ }]; - var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "route swap") - // console.log(tx.events['Swapped']); + var tx = await logGas(await calcRoute(ctx,decimalStr('10'),0.1,routes,pairs), ctx.sendParam(trader), "three hops swap") + console.log(tx.events['TestAmount']); var a_DODO = await ctx.DODO.methods.balanceOf(trader).call() var a_WETH = await ctx.WETH.methods.balanceOf(trader).call() console.log("After DODO:" + fromWei(a_DODO,'ether') + "; WETH:" + fromWei(a_WETH,'ether')); diff --git a/test/utils-v1/Context-route.ts b/test/utils-v1/Context-route.ts index 68a6a02..43761ac 100644 --- a/test/utils-v1/Context-route.ts +++ b/test/utils-v1/Context-route.ts @@ -57,7 +57,6 @@ export class DODOContext { lpFeeRate: string; mtFeeRate: string; k: string; - //token DODO:Contract; USDT:Contract; @@ -73,6 +72,7 @@ export class DODOContext { //SmartRoute SmartSwap: Contract; SmartApprove: Contract; + DODOSellHelper: Contract; constructor() {} @@ -213,13 +213,17 @@ export class DODOContext { .send(this.sendParam(this.Deployer)); await this.WETH_USDC.methods.enableTrading().send(this.sendParam(this.Deployer)); + this.DODOSellHelper = await contracts.newContract( + contracts.DODO_SELL_HELPER + ); + this.SmartApprove = await contracts.newContract( contracts.SMART_APPROVE ); this.SmartSwap = await contracts.newContract( contracts.SMART_SWAP, - [this.SmartApprove.options.address] + [this.SmartApprove.options.address,this.DODOSellHelper.options.address] ); await this.SmartApprove.methods.setSmartSwap(this.SmartSwap.options.address).send(this.sendParam(this.Deployer)); diff --git a/test/utils-v1/Contracts.ts b/test/utils-v1/Contracts.ts index a17f6b2..306f274 100644 --- a/test/utils-v1/Contracts.ts +++ b/test/utils-v1/Contracts.ts @@ -30,6 +30,7 @@ const LockedTokenVault = require(`${jsonPath}LockedTokenVault.json`) /*v1.5*/ const SmartSwap = require(`${jsonPath2}SmartSwap.json`) const SmartApprove = require(`${jsonPath2}SmartApprove.json`) +const DODOSellHelper = require(`${jsonPath2}DODOSellHelper.json`) /******/ import { getDefaultWeb3 } from './EVM'; @@ -53,6 +54,7 @@ export const DODO_MINE_READER_NAME = "DODOMineReader" /*v1.5*/ export const SMART_SWAP = "SmartSwap" export const SMART_APPROVE = "SmartApprove" +export const DODO_SELL_HELPER = "DODOSellHelper" /******/ var contractMap: { [name: string]: any } = {} @@ -73,6 +75,7 @@ contractMap[DODO_MINE_READER_NAME] = DODOMineReader /*v1.5*/ contractMap[SMART_SWAP] = SmartSwap contractMap[SMART_APPROVE] = SmartApprove +contractMap[DODO_SELL_HELPER] = DODOSellHelper /******/ interface ContractJson {