diff --git a/OneSplit.full.sol b/OneSplit.full.sol index 7982f2a..b4cc951 100644 --- a/OneSplit.full.sol +++ b/OneSplit.full.sol @@ -181,6 +181,7 @@ contract IOneSplitConsts { uint256 internal constant FLAG_DISABLE_MOONISWAP_DAI = 0x20000000000000000; uint256 internal constant FLAG_DISABLE_MOONISWAP_USDC = 0x40000000000000000; uint256 internal constant FLAG_DISABLE_MOONISWAP_POOL_TOKEN = 0x80000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x100000000000000000; } @@ -2067,7 +2068,7 @@ contract OneSplitRoot is IOneSplitView { using UniswapV2ExchangeLib for IUniswapV2Exchange; using ChaiHelper for IChai; - uint256 constant internal DEXES_COUNT = 34; + uint256 constant internal DEXES_COUNT = 35; IERC20 constant internal ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20 constant internal ZERO_ADDRESS = IERC20(0); @@ -2105,6 +2106,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); @@ -2466,7 +2468,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { true, // "Kyber 4" true, // "Mooniswap 2" true, // "Mooniswap 3" - true // "Mooniswap 4" + true, // "Mooniswap 4" + true // "Curve HBTC" ]; for (uint i = 0; i < DEXES_COUNT; i++) { @@ -2528,7 +2531,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4, invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_ETH) ? _calculateNoReturn : calculateMooniswapOverETH, invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_DAI) ? _calculateNoReturn : calculateMooniswapOverDAI, - invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_USDC) ? _calculateNoReturn : calculateMooniswapOverUSDC + invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_USDC) ? _calculateNoReturn : calculateMooniswapOverUSDC, + invert != flags.check(FLAG_DISABLE_CURVE_ALL | FLAG_DISABLE_CURVE_HBTC) ? _calculateNoReturn : calculateCurveHBTC ]; } @@ -2974,6 +2978,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, @@ -3825,7 +3850,8 @@ contract OneSplit is IOneSplit, OneSplitRoot { _swapOnKyber4, _swapOnMooniswapETH, _swapOnMooniswapDAI, - _swapOnMooniswapUSDC + _swapOnMooniswapUSDC, + _swapOnCurveHBTC ]; require(distribution.length <= reserves.length, "OneSplit: Distribution array should not exceed reserves array size"); @@ -4084,6 +4110,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 684e2d2..9243def 100644 --- a/OneSplitAudit.full.sol +++ b/OneSplitAudit.full.sol @@ -785,6 +785,12 @@ 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_MOONISWAP_ALL = 0x8000000000000000; + uint256 internal constant FLAG_DISABLE_MOONISWAP_ETH = 0x10000000000000000; + uint256 internal constant FLAG_DISABLE_MOONISWAP_DAI = 0x20000000000000000; + uint256 internal constant FLAG_DISABLE_MOONISWAP_USDC = 0x40000000000000000; + uint256 internal constant FLAG_DISABLE_MOONISWAP_POOL_TOKEN = 0x80000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x100000000000000000; } diff --git a/README.md b/README.md index ad2385a..177c866 100644 --- a/README.md +++ b/README.md @@ -501,6 +501,7 @@ flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_KYBER + ... | FLAG_DISABLE_KYBER_2 | `0x800000000000000` | Exclude the second multi-token `Kyber` reserve (exchange of any token to any is possible) from swap (see [KyberReserves](./KyberReserves.md)) | | FLAG_DISABLE_KYBER_3 | `0x1000000000000000` | Exclude the third multi-token `Kyber` reserve (exchange of any token to any is possible) from swap (see [KyberReserves](./KyberReserves.md)) | | FLAG_DISABLE_KYBER_4 | `0x2000000000000000` | Exclude the single-token `Kyber` reserve (single-token reserves does not intersect and the one that fits is selected) from swap (see [KyberReserves](./KyberReserves.md)) | + | FLAG_DISABLE_CURVE_HBTC | `0x100000000000000000` | Exclude `CurveHBTC` exchange from swap | **Example:** ``` diff --git a/contracts/IOneSplit.sol b/contracts/IOneSplit.sol index e7b8b1e..2373f85 100644 --- a/contracts/IOneSplit.sol +++ b/contracts/IOneSplit.sol @@ -100,6 +100,7 @@ contract IOneSplitConsts { uint256 internal constant FLAG_DISABLE_MOONISWAP_DAI = 0x20000000000000000; uint256 internal constant FLAG_DISABLE_MOONISWAP_USDC = 0x40000000000000000; uint256 internal constant FLAG_DISABLE_MOONISWAP_POOL_TOKEN = 0x80000000000000000; + uint256 internal constant FLAG_DISABLE_CURVE_HBTC = 0x100000000000000000; } diff --git a/contracts/OneSplitBase.sol b/contracts/OneSplitBase.sol index d47092b..d09c216 100644 --- a/contracts/OneSplitBase.sol +++ b/contracts/OneSplitBase.sol @@ -80,7 +80,7 @@ contract OneSplitRoot is IOneSplitView { using UniswapV2ExchangeLib for IUniswapV2Exchange; using ChaiHelper for IChai; - uint256 constant internal DEXES_COUNT = 34; + uint256 constant internal DEXES_COUNT = 35; IERC20 constant internal ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20 constant internal ZERO_ADDRESS = IERC20(0); @@ -118,6 +118,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); @@ -479,7 +480,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { true, // "Kyber 4" true, // "Mooniswap 2" true, // "Mooniswap 3" - true // "Mooniswap 4" + true, // "Mooniswap 4" + true // "Curve HBTC" ]; for (uint i = 0; i < DEXES_COUNT; i++) { @@ -541,7 +543,8 @@ contract OneSplitView is IOneSplitView, OneSplitRoot { invert != flags.check(FLAG_DISABLE_KYBER_ALL | FLAG_DISABLE_KYBER_4) ? _calculateNoReturn : calculateKyber4, invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_ETH) ? _calculateNoReturn : calculateMooniswapOverETH, invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_DAI) ? _calculateNoReturn : calculateMooniswapOverDAI, - invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_USDC) ? _calculateNoReturn : calculateMooniswapOverUSDC + invert != flags.check(FLAG_DISABLE_MOONISWAP_ALL | FLAG_DISABLE_MOONISWAP_USDC) ? _calculateNoReturn : calculateMooniswapOverUSDC, + invert != flags.check(FLAG_DISABLE_CURVE_ALL | FLAG_DISABLE_CURVE_HBTC) ? _calculateNoReturn : calculateCurveHBTC ]; } @@ -987,6 +990,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, @@ -1838,7 +1862,8 @@ contract OneSplit is IOneSplit, OneSplitRoot { _swapOnKyber4, _swapOnMooniswapETH, _swapOnMooniswapDAI, - _swapOnMooniswapUSDC + _swapOnMooniswapUSDC, + _swapOnCurveHBTC ]; require(distribution.length <= reserves.length, "OneSplit: Distribution array should not exceed reserves array size"); @@ -2097,6 +2122,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,