Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Add Curve HBTC Support #43

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 48 additions & 4 deletions OneSplit.full.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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
];
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions OneSplitAudit.full.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:**
```
Expand Down
1 change: 1 addition & 0 deletions contracts/IOneSplit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
51 changes: 47 additions & 4 deletions contracts/OneSplitBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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
];
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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,
Expand Down