From cd8c2787f8cfae2530b85c4873ff61844a3b585f Mon Sep 17 00:00:00 2001 From: "Christopher M. Mitchell" Date: Wed, 9 Sep 2020 19:51:46 -0700 Subject: [PATCH] Adding support for Curve HBTC pool --- OneSplit.full.sol | 52 +++++++++++++++++++++++++++++++++++--- OneSplitAudit.full.sol | 1 + README.md | 1 + contracts/IOneSplit.sol | 1 + contracts/OneSplitBase.sol | 51 ++++++++++++++++++++++++++++++++++--- 5 files changed, 98 insertions(+), 8 deletions(-) diff --git a/OneSplit.full.sol b/OneSplit.full.sol index 3bb381a..14baccc 100644 --- a/OneSplit.full.sol +++ b/OneSplit.full.sol @@ -176,6 +176,7 @@ contract IOneSplitConsts { uint256 internal constant FLAG_DISABLE_KYBER_3 = 0x1000000000000000; uint256 internal constant FLAG_DISABLE_KYBER_4 = 0x2000000000000000; uint256 internal constant FLAG_ENABLE_CHI_BURN_BY_ORIGIN = 0x4000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x8000000000000000; } @@ -1493,7 +1494,7 @@ contract OneSplitRoot is IOneSplitView { using UniswapV2ExchangeLib for IUniswapV2Exchange; using ChaiHelper for IChai; - uint256 constant internal DEXES_COUNT = 31; + uint256 constant internal DEXES_COUNT = 32; IERC20 constant internal ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IBancorEtherToken constant internal bancorEtherToken = IBancorEtherToken(0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315); @@ -1530,6 +1531,7 @@ contract OneSplitRoot is IOneSplitView { ICurve constant internal curveRenBTC = ICurve(0x93054188d876f558f4a66B2EF1d97d16eDf0895B); ICurve constant internal curveTBTC = ICurve(0x9726e9314eF1b96E45f40056bEd61A088897313E); ICurve constant internal curveSBTC = ICurve(0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714); + ICurve constant internal curveHBTC = ICurve(0x4CA9b3063Ec5866A4B82E437059D2C43d1be596F); IShell constant internal shell = IShell(0xA8253a440Be331dC4a7395B73948cCa6F19Dc97D); IAaveLendingPool constant internal aave = IAaveLendingPool(0x398eC7346DcD622eDc5ae82352F02bE94C62d119); ICompound constant internal compound = ICompound(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); @@ -1887,7 +1889,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { true, // "Kyber 1" true, // "Kyber 2" true, // "Kyber 3" - true // "Kyber 4" + true, // "Kyber 4" + true // "Curve HBTC" ]; for (uint i = 0; i < DEXES_COUNT; i++) { @@ -1946,7 +1949,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_1) ? _calculateNoReturn : calculateKyber1, invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_2) ? _calculateNoReturn : calculateKyber2, invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_3) ? _calculateNoReturn : calculateKyber3, - invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4 + invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4, + invert != flags.check(FLAG_DISABLE_CURVE_ALL | FLAG_DISABLE_CURVE_HBTC) ? _calculateNoReturn : calculateCurveHBTC ]; } @@ -2404,6 +2408,27 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { ), 150_000); } + function calculateCurveHBTC( + IERC20 fromToken, + IERC20 destToken, + uint256 amount, + uint256 parts, + uint256 /*flags*/ + ) internal view returns(uint256[] memory rets, uint256 gas) { + IERC20[] memory tokens = new IERC20[](3); + tokens[0] = hbtc; + tokens[1] = wbtc; + return (_calculateCurveSelector( + fromToken, + destToken, + amount, + parts, + curveHBTC, + false, + tokens + ), 130_000); + } + function calculateShell( IERC20 fromToken, IERC20 destToken, @@ -3182,7 +3207,8 @@ contract OneSplit is IOneSplit, OneSplitRoot { _swapOnKyber1, _swapOnKyber2, _swapOnKyber3, - _swapOnKyber4 + _swapOnKyber4, + _swapOnCurveHBTC ]; require(distribution.length <= reserves.length, "OneSplit: Distribution array should not exceed reserves array size"); @@ -3441,6 +3467,24 @@ contract OneSplit is IOneSplit, OneSplitRoot { curveSBTC.exchange(i - 1, j - 1, amount, 0); } + function _swapOnCurveHBTC( + IERC20 fromToken, + IERC20 destToken, + uint256 amount, + uint256 /*flags*/ + ) internal { + int128 i = (fromToken == hbtc ? 1 : 0) + + (fromToken == wbtc ? 2 : 0); + int128 j = (destToken == hbtc ? 1 : 0) + + (destToken == wbtc ? 2 : 0); + if (i == 0 || j == 0) { + return; + } + + fromToken.universalApprove(address(curveHBTC), amount); + curveHBTC.exchange(i - 1, j - 1, amount, 0); + } + function _swapOnDforceSwap( IERC20 fromToken, IERC20 destToken, diff --git a/OneSplitAudit.full.sol b/OneSplitAudit.full.sol index 8be027e..176a4be 100644 --- a/OneSplitAudit.full.sol +++ b/OneSplitAudit.full.sol @@ -753,6 +753,7 @@ contract IOneSplitConsts { uint256 internal constant FLAG_DISABLE_KYBER_3 = 0x1000000000000000; uint256 internal constant FLAG_DISABLE_KYBER_4 = 0x2000000000000000; uint256 internal constant FLAG_ENABLE_CHI_BURN_BY_ORIGIN = 0x4000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x8000000000000000; } diff --git a/README.md b/README.md index 61b8c1c..3e10e6c 100644 --- a/README.md +++ b/README.md @@ -279,6 +279,7 @@ flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_KYBER + ... | FLAG_DISABLE_CURVE_TBTC | `0x200000000` | Exclude `CurveTBtc` exchange from swap | | FLAG_DISABLE_DFORCE_SWAP | `0x4000000000` | Exclude `DforceSwap` exchange from swap | | FLAG_DISABLE_SHELL | `0x8000000000` | Exclude `Shellexchangers` exchange from swap | + | FLAG_DISABLE_CURVE_HBTC | `0x8000000000000000` | Exclude `CurveHBTC` exchange from swap | **Example:** ``` diff --git a/contracts/IOneSplit.sol b/contracts/IOneSplit.sol index f27e8be..01ac854 100644 --- a/contracts/IOneSplit.sol +++ b/contracts/IOneSplit.sol @@ -95,6 +95,7 @@ contract IOneSplitConsts { uint256 internal constant FLAG_DISABLE_KYBER_3 = 0x1000000000000000; uint256 internal constant FLAG_DISABLE_KYBER_4 = 0x2000000000000000; uint256 internal constant FLAG_ENABLE_CHI_BURN_BY_ORIGIN = 0x4000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x8000000000000000; } diff --git a/contracts/OneSplitBase.sol b/contracts/OneSplitBase.sol index 9316785..04a2182 100644 --- a/contracts/OneSplitBase.sol +++ b/contracts/OneSplitBase.sol @@ -79,7 +79,7 @@ contract OneSplitRoot is IOneSplitView { using UniswapV2ExchangeLib for IUniswapV2Exchange; using ChaiHelper for IChai; - uint256 constant internal DEXES_COUNT = 31; + uint256 constant internal DEXES_COUNT = 32; IERC20 constant internal ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IBancorEtherToken constant internal bancorEtherToken = IBancorEtherToken(0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315); @@ -116,6 +116,7 @@ contract OneSplitRoot is IOneSplitView { ICurve constant internal curveRenBTC = ICurve(0x93054188d876f558f4a66B2EF1d97d16eDf0895B); ICurve constant internal curveTBTC = ICurve(0x9726e9314eF1b96E45f40056bEd61A088897313E); ICurve constant internal curveSBTC = ICurve(0x7fC77b5c7614E1533320Ea6DDc2Eb61fa00A9714); + ICurve constant internal curveHBTC = ICurve(0x4CA9b3063Ec5866A4B82E437059D2C43d1be596F); IShell constant internal shell = IShell(0xA8253a440Be331dC4a7395B73948cCa6F19Dc97D); IAaveLendingPool constant internal aave = IAaveLendingPool(0x398eC7346DcD622eDc5ae82352F02bE94C62d119); ICompound constant internal compound = ICompound(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); @@ -473,7 +474,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { true, // "Kyber 1" true, // "Kyber 2" true, // "Kyber 3" - true // "Kyber 4" + true, // "Kyber 4" + true // "Curve HBTC" ]; for (uint i = 0; i < DEXES_COUNT; i++) { @@ -532,7 +534,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_1) ? _calculateNoReturn : calculateKyber1, invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_2) ? _calculateNoReturn : calculateKyber2, invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_3) ? _calculateNoReturn : calculateKyber3, - invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4 + invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4, + invert != flags.check(FLAG_DISABLE_CURVE_ALL | FLAG_DISABLE_CURVE_HBTC) ? _calculateNoReturn : calculateCurveHBTC ]; } @@ -990,6 +993,27 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { ), 150_000); } + function calculateCurveHBTC( + IERC20 fromToken, + IERC20 destToken, + uint256 amount, + uint256 parts, + uint256 /*flags*/ + ) internal view returns(uint256[] memory rets, uint256 gas) { + IERC20[] memory tokens = new IERC20[](3); + tokens[0] = hbtc; + tokens[1] = wbtc; + return (_calculateCurveSelector( + fromToken, + destToken, + amount, + parts, + curveHBTC, + false, + tokens + ), 130_000); + } + function calculateShell( IERC20 fromToken, IERC20 destToken, @@ -1768,7 +1792,8 @@ contract OneSplit is IOneSplit, OneSplitRoot { _swapOnKyber1, _swapOnKyber2, _swapOnKyber3, - _swapOnKyber4 + _swapOnKyber4, + _swapOnCurveHBTC ]; require(distribution.length <= reserves.length, "OneSplit: Distribution array should not exceed reserves array size"); @@ -2027,6 +2052,24 @@ contract OneSplit is IOneSplit, OneSplitRoot { curveSBTC.exchange(i - 1, j - 1, amount, 0); } + function _swapOnCurveHBTC( + IERC20 fromToken, + IERC20 destToken, + uint256 amount, + uint256 /*flags*/ + ) internal { + int128 i = (fromToken == hbtc ? 1 : 0) + + (fromToken == wbtc ? 2 : 0); + int128 j = (destToken == hbtc ? 1 : 0) + + (destToken == wbtc ? 2 : 0); + if (i == 0 || j == 0) { + return; + } + + fromToken.universalApprove(address(curveHBTC), amount); + curveHBTC.exchange(i - 1, j - 1, amount, 0); + } + function _swapOnDforceSwap( IERC20 fromToken, IERC20 destToken,