fix: Support Multiple Shells (#17)

* fix: Support Multiple Shells

* CHANGEGLOG
This commit is contained in:
Jacob Evans 2020-10-29 17:09:23 +10:00 committed by GitHub
parent 02006118c7
commit 717db99b38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 143 additions and 101 deletions

View File

@ -51,16 +51,15 @@ contract ShellBridge is
external
returns (bytes4 success)
{
// Decode the bridge data to get the `fromTokenAddress`.
(address fromTokenAddress) = abi.decode(bridgeData, (address));
// Decode the bridge data to get the `fromTokenAddress` and `pool`.
(address fromTokenAddress, address pool) = abi.decode(bridgeData, (address, address));
uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this));
IShell exchange = IShell(_getShellAddress());
// 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.
uint256 boughtAmount = exchange.originSwap(
uint256 boughtAmount = IShell(pool).originSwap(
fromTokenAddress,
toTokenAddress,
fromTokenBalance,

View File

@ -56,8 +56,6 @@ contract DeploymentConstants {
address constant private MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
/// @dev Mainnet address of the Mooniswap Registry contract
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
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
/// @dev Mainnet address of the DODO Helper contract
@ -303,16 +301,6 @@ contract DeploymentConstants {
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.
/// @return registry The DODO Registry contract address.
function _getDODORegistryAddress()

View File

@ -89,7 +89,7 @@ contract BridgeAdapter is
MixinMooniswap(addresses)
MixinMStable(addresses)
MixinOasis(addresses)
MixinShell(addresses)
MixinShell()
MixinSushiswap(addresses)
MixinUniswap(addresses)
MixinUniswapV2(addresses)

View File

@ -44,7 +44,6 @@ contract MixinAdapterAddresses
address uniswapV2Router;
address uniswapExchangeFactory;
address mStable;
address shell;
address dodoHelper;
// Other
address weth;

View File

@ -44,15 +44,6 @@ contract MixinShell is
{
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(
IERC20TokenV06 buyToken,
uint256 sellAmount,
@ -61,15 +52,15 @@ contract MixinShell is
internal
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.
IERC20TokenV06(fromTokenAddress).approveIfBelow(
address(SHELL),
pool,
sellAmount
);
boughtAmount = SHELL.originSwap(
boughtAmount = IShell(pool).originSwap(
fromTokenAddress,
address(buyToken),
// Sell all tokens we hold.

View File

@ -77,7 +77,6 @@ blockchainTests.resets('FillQuoteTransformer', env => {
mStable: NULL_ADDRESS,
weth: NULL_ADDRESS,
shellBridge: NULL_ADDRESS,
shell: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
dodoHelper: NULL_ADDRESS,

View File

@ -1,4 +1,13 @@
[
{
"version": "4.9.0",
"changes": [
{
"note": "Support multiple `Shells` by supplying the `pool` address",
"pr": 17
}
]
},
{
"version": "4.8.1",
"changes": [

View File

@ -28,13 +28,15 @@ contract ShellSampler is
/// @dev Default gas limit for Shell calls.
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 makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromShell(
address pool,
address takerToken,
address makerToken,
uint256[] memory takerTokenAmounts
@ -49,7 +51,7 @@ contract ShellSampler is
for (uint256 i = 0; i < numSamples; i++) {
try
IShell(_getShellAddress()).viewOriginSwap
IShell(pool).viewOriginSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
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 makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromShell(
address pool,
address takerToken,
address makerToken,
uint256[] memory makerTokenAmounts
@ -83,7 +87,7 @@ contract ShellSampler is
for (uint256 i = 0; i < numSamples; i++) {
try
IShell(_getShellAddress()).viewTargetSwap
IShell(pool).viewTargetSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, makerTokenAmounts[i])
returns (uint256 amount)

View File

@ -89,8 +89,28 @@ export const SOURCE_FLAGS: { [source in ERC20BridgeSource]: number } = Object.as
...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
* 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 } = {
DaiUsdc: {
@ -98,7 +118,7 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56',
tokens: ['0x6b175474e89094c44da98b954eedeac495271d0f', '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'],
tokens: [TOKENS.DAI, TOKENS.USDC],
},
// DaiUsdcUsdt: {
// exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
@ -106,9 +126,9 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
// poolAddress: '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c',
// tokens: [
// '0x6b175474e89094c44da98b954eedeac495271d0f',
// '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
// '0xdac17f958d2ee523a2206206994597c13d831ec7',
// TOKENS.DAI,
// TOKENS.USDC,
// TOKENS.USDT,
// ],
// },
DaiUsdcUsdtTusd: {
@ -116,12 +136,7 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51',
tokens: [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
'0x0000000000085d4780b73119b644ae5ecd22b376',
],
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
},
// Looks like it's dying.
DaiUsdcUsdtBusd: {
@ -130,10 +145,10 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
poolAddress: '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27',
tokens: [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
'0x4fabb145d64652a948d72533023f6e7a623c7c53',
TOKENS.DAI,
TOKENS.USDC,
TOKENS.USDT,
'0x4fabb145d64652a948d72533023f6e7a623c7c53', // bUSD
],
},
DaiUsdcUsdtSusd: {
@ -141,57 +156,41 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0xa5407eae9ba41422680e2e00537571bcc53efbfd',
tokens: [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
'0x57ab1ec28d129707052df4df418d58a2d46d5f51',
],
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD],
},
RenbtcWbtc: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x93054188d876f558f4a66b2ef1d97d16edf0895b',
tokens: ['0xeb4c2781e4eba804ce9a9803c67d0893436bb27d', '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'],
tokens: [TOKENS.RenBTC, TOKENS.WBTC],
},
RenbtcWbtcSbtc: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714',
tokens: [
'0xeb4c2781e4eba804ce9a9803c67d0893436bb27d',
'0x2260fac5e5542a773aa44fbcfedf7c193bc2c599',
'0xfe18be6b3bd88a2d2a7f928d00292e7a9963cfc6',
],
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
},
TriPool: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7',
tokens: [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
],
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
},
};
export const MAINNET_SWERVE_INFOS: { [name: string]: CurveInfo } = {
swUSD: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
poolAddress: '0x329239599afb305da0a2ec69c58f8a6697f9f88d', // _target: 0xa5407eae9ba41422680e2e00537571bcc53efbfd
tokens: [
'0x6b175474e89094c44da98b954eedeac495271d0f',
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
'0xdac17f958d2ee523a2206206994597c13d831ec7',
'0x0000000000085d4780b73119b644ae5ecd22b376',
],
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.TUSD],
},
};
export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
yVaultCurve: {
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
@ -232,10 +231,10 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
// buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
// poolAddress: '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b',
// tokens: [
// '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI
// '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
// '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
// '0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD
// TOKENS.DAI,
// TOKENS.USDC,
// TOKENS.USDT,
// 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 } = {
// USDC
['0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48']:
'0xaa55534443303041505200000000000000000000000000000000000000000000',
[TOKENS.USDC]: '0xaa55534443303041505200000000000000000000000000000000000000000000',
// AMPL
['0xd46ba6d942050d489dbd938a2c909a5d5039a161']:
'0xaad46ba6d942050d489dbd938a2c909a5d5039a1610000000000000000000000',
@ -263,8 +261,7 @@ export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
['0xdd974d5c2e2928dea5f71b9825b8b646686bd200']:
'0xaa4b4e435f4d4547414c41444f4e000000000000000000000000000000000000',
// sUSD
['0x57ab1ec28d129707052df4df418d58a2d46d5f51']:
'0xaa73555344000000000000000000000000000000000000000000000000000000',
[TOKENS.sUSD]: '0xaa73555344000000000000000000000000000000000000000000000000000000',
// SNX
['0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f']:
'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_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 WALLET_SIGNATURE = '0x04';
export const ONE_ETHER = new BigNumber(1e18);
@ -323,7 +331,7 @@ export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAd
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
shellBridge: '0x21fb3862eed7911e0f8219a077247b849846728d',
shellBridge: '0xf1c0811e3788caae7dbfae43da9d9131b1a8a148',
dodoBridge: '0xe9da66965a9344aab2167e6813c03f043cc7a6ca',
creamBridge: '0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25',
swerveBridge: '0xf9786d5eb1de47fa56a8f7bb387653c6d410bfee',

View File

@ -1,20 +1,13 @@
import { NULL_ADDRESS } from './constants';
import { NULL_ADDRESS, TOKENS } from './constants';
// 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 {
let intermediateToken = NULL_ADDRESS;
if (takerToken !== Tokens.WETH && makerToken !== Tokens.WETH) {
intermediateToken = Tokens.WETH;
} else if (takerToken === Tokens.USDC || makerToken === Tokens.USDC) {
intermediateToken = Tokens.DAI;
if (takerToken !== TOKENS.WETH && makerToken !== TOKENS.WETH) {
intermediateToken = TOKENS.WETH;
} else if (takerToken === TOKENS.USDC || makerToken === TOKENS.USDC) {
intermediateToken = TOKENS.DAI;
}
return intermediateToken;
}

View File

@ -33,6 +33,7 @@ import {
NativeCollapsedFill,
OptimizedMarketOrder,
OrderDomain,
ShellFillData,
SnowSwapFillData,
SushiSwapFillData,
SwerveFillData,
@ -331,6 +332,14 @@ export function createBridgeOrder(
createDODOBridgeData(takerToken, dodoFillData.poolAddress, dodoFillData.isSellBase),
);
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:
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
makerToken,
@ -380,6 +389,14 @@ function createBalancerBridgeData(takerToken: string, poolAddress: string): stri
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 {
const encoder = AbiEncoder.create([
{ name: 'path', type: 'address[]' },

View File

@ -14,6 +14,7 @@ import { getKyberReserveIdsForPair } from './kyber_utils';
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
import { getIntermediateTokens } from './multihop_utils';
import { SamplerContractOperation } from './sampler_contract_operation';
import { getShellsForPair } from './shell_utils';
import { SourceFilters } from './source_filters';
import {
BalancerFillData,
@ -30,6 +31,7 @@ import {
MooniswapFillData,
MultiBridgeFillData,
MultiHopFillData,
ShellFillData,
SnowSwapFillData,
SnowSwapInfo,
SourceQuoteOperation,
@ -840,19 +842,29 @@ export class SamplerOperations {
}
public getShellSellQuotes(
poolAddress: string,
makerToken: string,
takerToken: string,
takerFillAmounts: BigNumber[],
): SourceQuoteOperation {
): SourceQuoteOperation<ShellFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.Shell,
contract: this._samplerContract,
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(
poolAddress: string,
makerToken: string,
takerToken: string,
makerFillAmounts: BigNumber[],
@ -861,7 +873,15 @@ export class SamplerOperations {
source: ERC20BridgeSource.Shell,
contract: this._samplerContract,
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:
return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts);
return getShellsForPair(takerToken, makerToken).map(pool =>
this.getShellSellQuotes(pool, makerToken, takerToken, takerFillAmounts),
);
case ERC20BridgeSource.Dodo:
return this.getDODOSellQuotes(makerToken, takerToken, takerFillAmounts);
default:
@ -1290,7 +1312,9 @@ export class SamplerOperations {
),
);
case ERC20BridgeSource.Shell:
return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts);
return getShellsForPair(takerToken, makerToken).map(pool =>
this.getShellBuyQuotes(pool, makerToken, takerToken, makerFillAmounts),
);
case ERC20BridgeSource.Dodo:
return this.getDODOBuyQuotes(makerToken, takerToken, makerFillAmounts);
default:

View File

@ -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);
}

View File

@ -123,6 +123,10 @@ export interface SushiSwapFillData extends UniswapV2FillData {
router: string;
}
export interface ShellFillData extends FillData {
poolAddress: string;
}
export interface LiquidityProviderFillData extends FillData {
poolAddress: string;
}

View File

@ -391,7 +391,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Mooniswap]: { poolAddress: randomAddress() },
[ERC20BridgeSource.Native]: { order: createOrder() },
[ERC20BridgeSource.MultiHop]: {},
[ERC20BridgeSource.Shell]: {},
[ERC20BridgeSource.Shell]: { poolAddress: randomAddress() },
[ERC20BridgeSource.Cream]: { poolAddress: randomAddress() },
[ERC20BridgeSource.Dodo]: {},
};

View File

@ -329,7 +329,6 @@ export async function runMigrationsAsync(
mStable: NULL_ADDRESS,
shellBridge: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
shell: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
dodoHelper: NULL_ADDRESS,
snowSwapBridge: NULL_ADDRESS,