fix: Support Multiple Shells (#17)
* fix: Support Multiple Shells * CHANGEGLOG
This commit is contained in:
parent
02006118c7
commit
717db99b38
@ -51,16 +51,15 @@ contract ShellBridge is
|
|||||||
external
|
external
|
||||||
returns (bytes4 success)
|
returns (bytes4 success)
|
||||||
{
|
{
|
||||||
// Decode the bridge data to get the `fromTokenAddress`.
|
// Decode the bridge data to get the `fromTokenAddress` and `pool`.
|
||||||
(address fromTokenAddress) = abi.decode(bridgeData, (address));
|
(address fromTokenAddress, address pool) = abi.decode(bridgeData, (address, address));
|
||||||
|
|
||||||
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
|
||||||
IShell exchange = IShell(_getShellAddress());
|
|
||||||
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
|
||||||
LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance);
|
LibERC20Token.approveIfBelow(fromTokenAddress, pool, fromTokenBalance);
|
||||||
|
|
||||||
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
// Try to sell all of this contract's `fromTokenAddress` token balance.
|
||||||
uint256 boughtAmount = exchange.originSwap(
|
uint256 boughtAmount = IShell(pool).originSwap(
|
||||||
fromTokenAddress,
|
fromTokenAddress,
|
||||||
toTokenAddress,
|
toTokenAddress,
|
||||||
fromTokenBalance,
|
fromTokenBalance,
|
||||||
|
@ -56,8 +56,6 @@ contract DeploymentConstants {
|
|||||||
address constant private MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
|
address constant private MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
|
||||||
/// @dev Mainnet address of the Mooniswap Registry contract
|
/// @dev Mainnet address of the Mooniswap Registry contract
|
||||||
address constant private MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
|
address constant private MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
|
||||||
/// @dev Mainnet address of the Shell contract
|
|
||||||
address constant private SHELL_CONTRACT = 0x2E703D658f8dd21709a7B458967aB4081F8D3d05;
|
|
||||||
/// @dev Mainnet address of the DODO Registry (ZOO) contract
|
/// @dev Mainnet address of the DODO Registry (ZOO) contract
|
||||||
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
||||||
/// @dev Mainnet address of the DODO Helper contract
|
/// @dev Mainnet address of the DODO Helper contract
|
||||||
@ -303,16 +301,6 @@ contract DeploymentConstants {
|
|||||||
return MOONISWAP_REGISTRY;
|
return MOONISWAP_REGISTRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Shell contract address.
|
|
||||||
/// @return registry The Shell contract address.
|
|
||||||
function _getShellAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address)
|
|
||||||
{
|
|
||||||
return SHELL_CONTRACT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the DODO Registry contract address.
|
/// @dev An overridable way to retrieve the DODO Registry contract address.
|
||||||
/// @return registry The DODO Registry contract address.
|
/// @return registry The DODO Registry contract address.
|
||||||
function _getDODORegistryAddress()
|
function _getDODORegistryAddress()
|
||||||
|
@ -89,7 +89,7 @@ contract BridgeAdapter is
|
|||||||
MixinMooniswap(addresses)
|
MixinMooniswap(addresses)
|
||||||
MixinMStable(addresses)
|
MixinMStable(addresses)
|
||||||
MixinOasis(addresses)
|
MixinOasis(addresses)
|
||||||
MixinShell(addresses)
|
MixinShell()
|
||||||
MixinSushiswap(addresses)
|
MixinSushiswap(addresses)
|
||||||
MixinUniswap(addresses)
|
MixinUniswap(addresses)
|
||||||
MixinUniswapV2(addresses)
|
MixinUniswapV2(addresses)
|
||||||
|
@ -44,7 +44,6 @@ contract MixinAdapterAddresses
|
|||||||
address uniswapV2Router;
|
address uniswapV2Router;
|
||||||
address uniswapExchangeFactory;
|
address uniswapExchangeFactory;
|
||||||
address mStable;
|
address mStable;
|
||||||
address shell;
|
|
||||||
address dodoHelper;
|
address dodoHelper;
|
||||||
// Other
|
// Other
|
||||||
address weth;
|
address weth;
|
||||||
|
@ -44,15 +44,6 @@ contract MixinShell is
|
|||||||
{
|
{
|
||||||
using LibERC20TokenV06 for IERC20TokenV06;
|
using LibERC20TokenV06 for IERC20TokenV06;
|
||||||
|
|
||||||
/// @dev Mainnet address of the `Shell` contract.
|
|
||||||
IShell private immutable SHELL;
|
|
||||||
|
|
||||||
constructor(AdapterAddresses memory addresses)
|
|
||||||
public
|
|
||||||
{
|
|
||||||
SHELL = IShell(addresses.shell);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _tradeShell(
|
function _tradeShell(
|
||||||
IERC20TokenV06 buyToken,
|
IERC20TokenV06 buyToken,
|
||||||
uint256 sellAmount,
|
uint256 sellAmount,
|
||||||
@ -61,15 +52,15 @@ contract MixinShell is
|
|||||||
internal
|
internal
|
||||||
returns (uint256 boughtAmount)
|
returns (uint256 boughtAmount)
|
||||||
{
|
{
|
||||||
(address fromTokenAddress) = abi.decode(bridgeData, (address));
|
(address fromTokenAddress, address pool) = abi.decode(bridgeData, (address, address));
|
||||||
|
|
||||||
// Grant the Shell contract an allowance to sell the first token.
|
// Grant the Shell contract an allowance to sell the first token.
|
||||||
IERC20TokenV06(fromTokenAddress).approveIfBelow(
|
IERC20TokenV06(fromTokenAddress).approveIfBelow(
|
||||||
address(SHELL),
|
pool,
|
||||||
sellAmount
|
sellAmount
|
||||||
);
|
);
|
||||||
|
|
||||||
boughtAmount = SHELL.originSwap(
|
boughtAmount = IShell(pool).originSwap(
|
||||||
fromTokenAddress,
|
fromTokenAddress,
|
||||||
address(buyToken),
|
address(buyToken),
|
||||||
// Sell all tokens we hold.
|
// Sell all tokens we hold.
|
||||||
|
@ -77,7 +77,6 @@ blockchainTests.resets('FillQuoteTransformer', env => {
|
|||||||
mStable: NULL_ADDRESS,
|
mStable: NULL_ADDRESS,
|
||||||
weth: NULL_ADDRESS,
|
weth: NULL_ADDRESS,
|
||||||
shellBridge: NULL_ADDRESS,
|
shellBridge: NULL_ADDRESS,
|
||||||
shell: NULL_ADDRESS,
|
|
||||||
creamBridge: NULL_ADDRESS,
|
creamBridge: NULL_ADDRESS,
|
||||||
dodoBridge: NULL_ADDRESS,
|
dodoBridge: NULL_ADDRESS,
|
||||||
dodoHelper: NULL_ADDRESS,
|
dodoHelper: NULL_ADDRESS,
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "4.9.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Support multiple `Shells` by supplying the `pool` address",
|
||||||
|
"pr": 17
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "4.8.1",
|
"version": "4.8.1",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -28,13 +28,15 @@ contract ShellSampler is
|
|||||||
/// @dev Default gas limit for Shell calls.
|
/// @dev Default gas limit for Shell calls.
|
||||||
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
|
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
|
||||||
|
|
||||||
/// @dev Sample sell quotes from the Shell contract
|
/// @dev Sample sell quotes from the Shell pool contract
|
||||||
|
/// @param pool Address of the Shell pool contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromShell(
|
function sampleSellsFromShell(
|
||||||
|
address pool,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -49,7 +51,7 @@ contract ShellSampler is
|
|||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
try
|
try
|
||||||
IShell(_getShellAddress()).viewOriginSwap
|
IShell(pool).viewOriginSwap
|
||||||
{gas: DEFAULT_CALL_GAS}
|
{gas: DEFAULT_CALL_GAS}
|
||||||
(takerToken, makerToken, takerTokenAmounts[i])
|
(takerToken, makerToken, takerTokenAmounts[i])
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
@ -62,13 +64,15 @@ contract ShellSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from Shell contract
|
/// @dev Sample buy quotes from Shell pool contract
|
||||||
|
/// @param pool Address of the Shell pool contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromShell(
|
function sampleBuysFromShell(
|
||||||
|
address pool,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -83,7 +87,7 @@ contract ShellSampler is
|
|||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
try
|
try
|
||||||
IShell(_getShellAddress()).viewTargetSwap
|
IShell(pool).viewTargetSwap
|
||||||
{gas: DEFAULT_CALL_GAS}
|
{gas: DEFAULT_CALL_GAS}
|
||||||
(takerToken, makerToken, makerTokenAmounts[i])
|
(takerToken, makerToken, makerTokenAmounts[i])
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
|
@ -89,8 +89,28 @@ export const SOURCE_FLAGS: { [source in ERC20BridgeSource]: number } = Object.as
|
|||||||
...Object.values(ERC20BridgeSource).map((source: ERC20BridgeSource, index) => ({ [source]: 1 << index })),
|
...Object.values(ERC20BridgeSource).map((source: ERC20BridgeSource, index) => ({ [source]: 1 << index })),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Mainnet tokens
|
||||||
|
// Not an exhaustive list, just enough so we don't repeat ourselves
|
||||||
|
export const TOKENS = {
|
||||||
|
WETH: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
||||||
|
// Stable Coins
|
||||||
|
DAI: '0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||||
|
USDC: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||||
|
USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
|
sUSD: '0x57ab1ec28d129707052df4df418d58a2d46d5f51',
|
||||||
|
TUSD: '0x0000000000085d4780b73119b644ae5ecd22b376',
|
||||||
|
// Bitcoins
|
||||||
|
WBTC: '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
|
||||||
|
RenBTC: '0xeb4c2781e4eba804ce9a9803c67d0893436bb27d',
|
||||||
|
sBTC: '0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6',
|
||||||
|
// Other
|
||||||
|
MKR: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mainnet Curve configuration
|
* Mainnet Curve configuration
|
||||||
|
* The tokens are in order of their index, which each curve defines
|
||||||
|
* I.e DaiUsdc curve has DAI as index 0 and USDC as index 1
|
||||||
*/
|
*/
|
||||||
export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
||||||
DaiUsdc: {
|
DaiUsdc: {
|
||||||
@ -98,7 +118,7 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
poolAddress: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
|
poolAddress: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
|
||||||
tokens: ['0x6b175474e89094c44da98b954eedeac495271d0f', '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
|
tokens: [TOKENS.DAI, TOKENS.USDC],
|
||||||
},
|
},
|
||||||
// DaiUsdcUsdt: {
|
// DaiUsdcUsdt: {
|
||||||
// exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
// exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
@ -106,9 +126,9 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
// poolAddress: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
|
// poolAddress: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
|
||||||
// tokens: [
|
// tokens: [
|
||||||
// '0x6b175474e89094c44da98b954eedeac495271d0f',
|
// TOKENS.DAI,
|
||||||
// '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
// TOKENS.USDC,
|
||||||
// '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
// TOKENS.USDT,
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
DaiUsdcUsdtTusd: {
|
DaiUsdcUsdtTusd: {
|
||||||
@ -116,12 +136,7 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
poolAddress: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
|
poolAddress: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
|
||||||
tokens: [
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
|
||||||
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
||||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
||||||
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
||||||
'0x0000000000085d4780b73119b644ae5ecd22b376',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
// Looks like it's dying.
|
// Looks like it's dying.
|
||||||
DaiUsdcUsdtBusd: {
|
DaiUsdcUsdtBusd: {
|
||||||
@ -130,10 +145,10 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
poolAddress: '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27',
|
poolAddress: '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27',
|
||||||
tokens: [
|
tokens: [
|
||||||
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
TOKENS.DAI,
|
||||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
TOKENS.USDC,
|
||||||
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
TOKENS.USDT,
|
||||||
'0x4fabb145d64652a948d72533023f6e7a623c7c53',
|
'0x4fabb145d64652a948d72533023f6e7a623c7c53', // bUSD
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
DaiUsdcUsdtSusd: {
|
DaiUsdcUsdtSusd: {
|
||||||
@ -141,57 +156,41 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: '0xa5407eae9ba41422680e2e00537571bcc53efbfd',
|
poolAddress: '0xa5407eae9ba41422680e2e00537571bcc53efbfd',
|
||||||
tokens: [
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD],
|
||||||
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
||||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
||||||
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
||||||
'0x57ab1ec28d129707052df4df418d58a2d46d5f51',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
RenbtcWbtc: {
|
RenbtcWbtc: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: '0x93054188d876f558f4a66b2ef1d97d16edf0895b',
|
poolAddress: '0x93054188d876f558f4a66b2ef1d97d16edf0895b',
|
||||||
tokens: ['0xeb4c2781e4eba804ce9a9803c67d0893436bb27d', '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'],
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC],
|
||||||
},
|
},
|
||||||
RenbtcWbtcSbtc: {
|
RenbtcWbtcSbtc: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714',
|
poolAddress: '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714',
|
||||||
tokens: [
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
'0xeb4c2781e4eba804ce9a9803c67d0893436bb27d',
|
|
||||||
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
|
|
||||||
'0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
TriPool: {
|
TriPool: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
|
poolAddress: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
|
||||||
tokens: [
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
||||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
||||||
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MAINNET_SWERVE_INFOS: { [name: string]: CurveInfo } = {
|
export const MAINNET_SWERVE_INFOS: { [name: string]: CurveInfo } = {
|
||||||
swUSD: {
|
swUSD: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: '0x329239599afb305da0a2ec69c58f8a6697f9f88d', // _target: 0xa5407eae9ba41422680e2e00537571bcc53efbfd
|
poolAddress: '0x329239599afb305da0a2ec69c58f8a6697f9f88d', // _target: 0xa5407eae9ba41422680e2e00537571bcc53efbfd
|
||||||
tokens: [
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
|
||||||
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
||||||
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
||||||
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
|
||||||
'0x0000000000085d4780b73119b644ae5ecd22b376',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
|
export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
|
||||||
yVaultCurve: {
|
yVaultCurve: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
@ -232,10 +231,10 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
// poolAddress: '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b',
|
// poolAddress: '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b',
|
||||||
// tokens: [
|
// tokens: [
|
||||||
// '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
|
// TOKENS.DAI,
|
||||||
// '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
|
// TOKENS.USDC,
|
||||||
// '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
|
// TOKENS.USDT,
|
||||||
// '0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD
|
// TOKENS.TUSD,
|
||||||
// ],
|
// ],
|
||||||
// },
|
// },
|
||||||
};
|
};
|
||||||
@ -248,8 +247,7 @@ export const MAINNET_KYBER_RESERVE_IDS: { [name: string]: string } = {
|
|||||||
|
|
||||||
export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
||||||
// USDC
|
// USDC
|
||||||
['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']:
|
[TOKENS.USDC]: '0xaa55534443303041505200000000000000000000000000000000000000000000',
|
||||||
'0xaa55534443303041505200000000000000000000000000000000000000000000',
|
|
||||||
// AMPL
|
// AMPL
|
||||||
['0xd46ba6d942050d489dbd938a2c909a5d5039a161']:
|
['0xd46ba6d942050d489dbd938a2c909a5d5039a161']:
|
||||||
'0xaad46ba6d942050d489dbd938a2c909a5d5039a1610000000000000000000000',
|
'0xaad46ba6d942050d489dbd938a2c909a5d5039a1610000000000000000000000',
|
||||||
@ -263,8 +261,7 @@ export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
|||||||
['0xdd974d5c2e2928dea5f71b9825b8b646686bd200']:
|
['0xdd974d5c2e2928dea5f71b9825b8b646686bd200']:
|
||||||
'0xaa4b4e435f4d4547414c41444f4e000000000000000000000000000000000000',
|
'0xaa4b4e435f4d4547414c41444f4e000000000000000000000000000000000000',
|
||||||
// sUSD
|
// sUSD
|
||||||
['0x57ab1ec28d129707052df4df418d58a2d46d5f51']:
|
[TOKENS.sUSD]: '0xaa73555344000000000000000000000000000000000000000000000000000000',
|
||||||
'0xaa73555344000000000000000000000000000000000000000000000000000000',
|
|
||||||
// SNX
|
// SNX
|
||||||
['0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f']:
|
['0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f']:
|
||||||
'0xaa534e5800000000000000000000000000000000000000000000000000000000',
|
'0xaa534e5800000000000000000000000000000000000000000000000000000000',
|
||||||
@ -278,6 +275,17 @@ export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
|||||||
|
|
||||||
export const MAINNET_SUSHI_SWAP_ROUTER = '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F';
|
export const MAINNET_SUSHI_SWAP_ROUTER = '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F';
|
||||||
|
|
||||||
|
export const MAINNET_SHELL_POOLS = {
|
||||||
|
StableCoins: {
|
||||||
|
poolAddress: '0x2E703D658f8dd21709a7B458967aB4081F8D3d05',
|
||||||
|
tokens: [TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD, TOKENS.DAI],
|
||||||
|
},
|
||||||
|
Bitcoin: {
|
||||||
|
poolAddress: '0x02Af7C867d6Ddd2c87dEcec2E4AFF809ee118FBb',
|
||||||
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const ERC20_PROXY_ID = '0xf47261b0';
|
export const ERC20_PROXY_ID = '0xf47261b0';
|
||||||
export const WALLET_SIGNATURE = '0x04';
|
export const WALLET_SIGNATURE = '0x04';
|
||||||
export const ONE_ETHER = new BigNumber(1e18);
|
export const ONE_ETHER = new BigNumber(1e18);
|
||||||
@ -323,7 +331,7 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
|
|||||||
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
|
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
|
||||||
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
|
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
|
||||||
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
|
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
|
||||||
shellBridge: '0x21fb3862eed7911e0f8219a077247b849846728d',
|
shellBridge: '0xf1c0811e3788caae7dbfae43da9d9131b1a8a148',
|
||||||
dodoBridge: '0xe9da66965a9344aab2167e6813c03f043cc7a6ca',
|
dodoBridge: '0xe9da66965a9344aab2167e6813c03f043cc7a6ca',
|
||||||
creamBridge: '0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25',
|
creamBridge: '0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25',
|
||||||
swerveBridge: '0xf9786d5eb1de47fa56a8f7bb387653c6d410bfee',
|
swerveBridge: '0xf9786d5eb1de47fa56a8f7bb387653c6d410bfee',
|
||||||
|
@ -1,20 +1,13 @@
|
|||||||
import { NULL_ADDRESS } from './constants';
|
import { NULL_ADDRESS, TOKENS } from './constants';
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
// tslint:disable completed-docs
|
||||||
// tslint:disable enum-naming
|
|
||||||
enum Tokens {
|
|
||||||
WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
|
||||||
DAI = '0x6b175474e89094c44da98b954eedeac495271d0f',
|
|
||||||
USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
|
||||||
MKR = '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMultiBridgeIntermediateToken(takerToken: string, makerToken: string): string {
|
export function getMultiBridgeIntermediateToken(takerToken: string, makerToken: string): string {
|
||||||
let intermediateToken = NULL_ADDRESS;
|
let intermediateToken = NULL_ADDRESS;
|
||||||
if (takerToken !== Tokens.WETH && makerToken !== Tokens.WETH) {
|
if (takerToken !== TOKENS.WETH && makerToken !== TOKENS.WETH) {
|
||||||
intermediateToken = Tokens.WETH;
|
intermediateToken = TOKENS.WETH;
|
||||||
} else if (takerToken === Tokens.USDC || makerToken === Tokens.USDC) {
|
} else if (takerToken === TOKENS.USDC || makerToken === TOKENS.USDC) {
|
||||||
intermediateToken = Tokens.DAI;
|
intermediateToken = TOKENS.DAI;
|
||||||
}
|
}
|
||||||
return intermediateToken;
|
return intermediateToken;
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
NativeCollapsedFill,
|
NativeCollapsedFill,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
OrderDomain,
|
OrderDomain,
|
||||||
|
ShellFillData,
|
||||||
SnowSwapFillData,
|
SnowSwapFillData,
|
||||||
SushiSwapFillData,
|
SushiSwapFillData,
|
||||||
SwerveFillData,
|
SwerveFillData,
|
||||||
@ -331,6 +332,14 @@ export function createBridgeOrder(
|
|||||||
createDODOBridgeData(takerToken, dodoFillData.poolAddress, dodoFillData.isSellBase),
|
createDODOBridgeData(takerToken, dodoFillData.poolAddress, dodoFillData.isSellBase),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case ERC20BridgeSource.Shell:
|
||||||
|
const shellFillData = (fill as CollapsedFill<ShellFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
|
makerToken,
|
||||||
|
bridgeAddress,
|
||||||
|
createShellBridgeData(takerToken, shellFillData.poolAddress),
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
makerToken,
|
makerToken,
|
||||||
@ -380,6 +389,14 @@ function createBalancerBridgeData(takerToken: string, poolAddress: string): stri
|
|||||||
return encoder.encode({ takerToken, poolAddress });
|
return encoder.encode({ takerToken, poolAddress });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createShellBridgeData(takerToken: string, poolAddress: string): string {
|
||||||
|
const encoder = AbiEncoder.create([
|
||||||
|
{ name: 'takerToken', type: 'address' },
|
||||||
|
{ name: 'poolAddress', type: 'address' },
|
||||||
|
]);
|
||||||
|
return encoder.encode({ takerToken, poolAddress });
|
||||||
|
}
|
||||||
|
|
||||||
function createBancorBridgeData(path: string[], networkAddress: string): string {
|
function createBancorBridgeData(path: string[], networkAddress: string): string {
|
||||||
const encoder = AbiEncoder.create([
|
const encoder = AbiEncoder.create([
|
||||||
{ name: 'path', type: 'address[]' },
|
{ name: 'path', type: 'address[]' },
|
||||||
|
@ -14,6 +14,7 @@ import { getKyberReserveIdsForPair } from './kyber_utils';
|
|||||||
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
||||||
import { getIntermediateTokens } from './multihop_utils';
|
import { getIntermediateTokens } from './multihop_utils';
|
||||||
import { SamplerContractOperation } from './sampler_contract_operation';
|
import { SamplerContractOperation } from './sampler_contract_operation';
|
||||||
|
import { getShellsForPair } from './shell_utils';
|
||||||
import { SourceFilters } from './source_filters';
|
import { SourceFilters } from './source_filters';
|
||||||
import {
|
import {
|
||||||
BalancerFillData,
|
BalancerFillData,
|
||||||
@ -30,6 +31,7 @@ import {
|
|||||||
MooniswapFillData,
|
MooniswapFillData,
|
||||||
MultiBridgeFillData,
|
MultiBridgeFillData,
|
||||||
MultiHopFillData,
|
MultiHopFillData,
|
||||||
|
ShellFillData,
|
||||||
SnowSwapFillData,
|
SnowSwapFillData,
|
||||||
SnowSwapInfo,
|
SnowSwapInfo,
|
||||||
SourceQuoteOperation,
|
SourceQuoteOperation,
|
||||||
@ -840,19 +842,29 @@ export class SamplerOperations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getShellSellQuotes(
|
public getShellSellQuotes(
|
||||||
|
poolAddress: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
takerFillAmounts: BigNumber[],
|
takerFillAmounts: BigNumber[],
|
||||||
): SourceQuoteOperation {
|
): SourceQuoteOperation<ShellFillData> {
|
||||||
return new SamplerContractOperation({
|
return new SamplerContractOperation({
|
||||||
source: ERC20BridgeSource.Shell,
|
source: ERC20BridgeSource.Shell,
|
||||||
contract: this._samplerContract,
|
contract: this._samplerContract,
|
||||||
function: this._samplerContract.sampleSellsFromShell,
|
function: this._samplerContract.sampleSellsFromShell,
|
||||||
params: [takerToken, makerToken, takerFillAmounts],
|
params: [poolAddress, takerToken, makerToken, takerFillAmounts],
|
||||||
|
callback: (callResults: string, fillData: ShellFillData): BigNumber[] => {
|
||||||
|
const samples = this._samplerContract.getABIDecodedReturnData<BigNumber[]>(
|
||||||
|
'sampleSellsFromShell',
|
||||||
|
callResults,
|
||||||
|
);
|
||||||
|
fillData.poolAddress = poolAddress;
|
||||||
|
return samples;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getShellBuyQuotes(
|
public getShellBuyQuotes(
|
||||||
|
poolAddress: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerFillAmounts: BigNumber[],
|
makerFillAmounts: BigNumber[],
|
||||||
@ -861,7 +873,15 @@ export class SamplerOperations {
|
|||||||
source: ERC20BridgeSource.Shell,
|
source: ERC20BridgeSource.Shell,
|
||||||
contract: this._samplerContract,
|
contract: this._samplerContract,
|
||||||
function: this._samplerContract.sampleBuysFromShell,
|
function: this._samplerContract.sampleBuysFromShell,
|
||||||
params: [takerToken, makerToken, makerFillAmounts],
|
params: [poolAddress, takerToken, makerToken, makerFillAmounts],
|
||||||
|
callback: (callResults: string, fillData: ShellFillData): BigNumber[] => {
|
||||||
|
const samples = this._samplerContract.getABIDecodedReturnData<BigNumber[]>(
|
||||||
|
'sampleBuysFromShell',
|
||||||
|
callResults,
|
||||||
|
);
|
||||||
|
fillData.poolAddress = poolAddress;
|
||||||
|
return samples;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,7 +1192,9 @@ export class SamplerOperations {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
case ERC20BridgeSource.Shell:
|
case ERC20BridgeSource.Shell:
|
||||||
return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts);
|
return getShellsForPair(takerToken, makerToken).map(pool =>
|
||||||
|
this.getShellSellQuotes(pool, makerToken, takerToken, takerFillAmounts),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.Dodo:
|
case ERC20BridgeSource.Dodo:
|
||||||
return this.getDODOSellQuotes(makerToken, takerToken, takerFillAmounts);
|
return this.getDODOSellQuotes(makerToken, takerToken, takerFillAmounts);
|
||||||
default:
|
default:
|
||||||
@ -1290,7 +1312,9 @@ export class SamplerOperations {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
case ERC20BridgeSource.Shell:
|
case ERC20BridgeSource.Shell:
|
||||||
return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
return getShellsForPair(takerToken, makerToken).map(pool =>
|
||||||
|
this.getShellBuyQuotes(pool, makerToken, takerToken, makerFillAmounts),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.Dodo:
|
case ERC20BridgeSource.Dodo:
|
||||||
return this.getDODOBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
return this.getDODOBuyQuotes(makerToken, takerToken, makerFillAmounts);
|
||||||
default:
|
default:
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { MAINNET_SHELL_POOLS } from './constants';
|
||||||
|
|
||||||
|
// tslint:disable completed-docs
|
||||||
|
export function getShellsForPair(takerToken: string, makerToken: string): string[] {
|
||||||
|
return Object.values(MAINNET_SHELL_POOLS)
|
||||||
|
.filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)))
|
||||||
|
.map(i => i.poolAddress);
|
||||||
|
}
|
@ -123,6 +123,10 @@ export interface SushiSwapFillData extends UniswapV2FillData {
|
|||||||
router: string;
|
router: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ShellFillData extends FillData {
|
||||||
|
poolAddress: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LiquidityProviderFillData extends FillData {
|
export interface LiquidityProviderFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.Mooniswap]: { poolAddress: randomAddress() },
|
[ERC20BridgeSource.Mooniswap]: { poolAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Native]: { order: createOrder() },
|
[ERC20BridgeSource.Native]: { order: createOrder() },
|
||||||
[ERC20BridgeSource.MultiHop]: {},
|
[ERC20BridgeSource.MultiHop]: {},
|
||||||
[ERC20BridgeSource.Shell]: {},
|
[ERC20BridgeSource.Shell]: { poolAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Cream]: { poolAddress: randomAddress() },
|
[ERC20BridgeSource.Cream]: { poolAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Dodo]: {},
|
[ERC20BridgeSource.Dodo]: {},
|
||||||
};
|
};
|
||||||
|
@ -329,7 +329,6 @@ export async function runMigrationsAsync(
|
|||||||
mStable: NULL_ADDRESS,
|
mStable: NULL_ADDRESS,
|
||||||
shellBridge: NULL_ADDRESS,
|
shellBridge: NULL_ADDRESS,
|
||||||
creamBridge: NULL_ADDRESS,
|
creamBridge: NULL_ADDRESS,
|
||||||
shell: NULL_ADDRESS,
|
|
||||||
dodoBridge: NULL_ADDRESS,
|
dodoBridge: NULL_ADDRESS,
|
||||||
dodoHelper: NULL_ADDRESS,
|
dodoHelper: NULL_ADDRESS,
|
||||||
snowSwapBridge: NULL_ADDRESS,
|
snowSwapBridge: NULL_ADDRESS,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user