From 00f55be83ef3187ddbbf90e026fe96670523cc81 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Tue, 29 Sep 2020 12:59:54 -0700 Subject: [PATCH 01/10] Added cream bridge contract --- .../contracts/src/bridges/CreamBridge.sol | 103 ++++++++++++++++++ contracts/asset-proxy/package.json | 2 +- contracts/asset-proxy/src/artifacts.ts | 2 + contracts/asset-proxy/src/wrappers.ts | 1 + contracts/asset-proxy/test/artifacts.ts | 2 + contracts/asset-proxy/test/wrappers.ts | 1 + contracts/asset-proxy/tsconfig.json | 2 + 7 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol diff --git a/contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol b/contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol new file mode 100644 index 0000000000..c1a5750afa --- /dev/null +++ b/contracts/asset-proxy/contracts/src/bridges/CreamBridge.sol @@ -0,0 +1,103 @@ + +/* + + Copyright 2020 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; +import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol"; +import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol"; +import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; +import "../interfaces/IERC20Bridge.sol"; +import "../interfaces/IBalancerPool.sol"; + + +contract CreamBridge is + IERC20Bridge, + IWallet, + DeploymentConstants +{ + /// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of + /// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress` + /// token encoded in the bridge data, then transfers the bought + /// tokens to `to`. + /// @param toTokenAddress The token to buy and transfer to `to`. + /// @param from The maker (this contract). + /// @param to The recipient of the bought tokens. + /// @param amount Minimum amount of `toTokenAddress` tokens to buy. + /// @param bridgeData The abi-encoded addresses of the "from" token and Balancer pool. + /// @return success The magic bytes if successful. + function bridgeTransferFrom( + address toTokenAddress, + address from, + address to, + uint256 amount, + bytes calldata bridgeData + ) + external + returns (bytes4 success) + { + // Decode the bridge data. + (address fromTokenAddress, address poolAddress) = abi.decode( + bridgeData, + (address, address) + ); + require(toTokenAddress != fromTokenAddress, "CreamBridge/INVALID_PAIR"); + + uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); + // Grant an allowance to the exchange to spend `fromTokenAddress` token. + LibERC20Token.approveIfBelow(fromTokenAddress, poolAddress, fromTokenBalance); + + // Sell all of this contract's `fromTokenAddress` token balance. + (uint256 boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn( + fromTokenAddress, // tokenIn + fromTokenBalance, // tokenAmountIn + toTokenAddress, // tokenOut + amount, // minAmountOut + uint256(-1) // maxPrice + ); + + // Transfer the converted `toToken`s to `to`. + LibERC20Token.transfer(toTokenAddress, to, boughtAmount); + + emit ERC20BridgeTransfer( + fromTokenAddress, + toTokenAddress, + fromTokenBalance, + boughtAmount, + from, + to + ); + return BRIDGE_SUCCESS; + } + + /// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker + /// and sign for itself in orders. Always succeeds. + /// @return magicValue Magic success bytes, always. + function isValidSignature( + bytes32, + bytes calldata + ) + external + view + returns (bytes4 magicValue) + { + return LEGACY_WALLET_MAGIC_VALUE; + } +} diff --git a/contracts/asset-proxy/package.json b/contracts/asset-proxy/package.json index cf4e4f3222..ae00c94618 100644 --- a/contracts/asset-proxy/package.json +++ b/contracts/asset-proxy/package.json @@ -38,7 +38,7 @@ "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { - "abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|StaticCallProxy|SushiSwapBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json", + "abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CreamBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|StaticCallProxy|SushiSwapBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { diff --git a/contracts/asset-proxy/src/artifacts.ts b/contracts/asset-proxy/src/artifacts.ts index 5385d5d000..57e37ce8ff 100644 --- a/contracts/asset-proxy/src/artifacts.ts +++ b/contracts/asset-proxy/src/artifacts.ts @@ -8,6 +8,7 @@ import { ContractArtifact } from 'ethereum-types'; import * as BalancerBridge from '../generated-artifacts/BalancerBridge.json'; import * as BancorBridge from '../generated-artifacts/BancorBridge.json'; import * as ChaiBridge from '../generated-artifacts/ChaiBridge.json'; +import * as CreamBridge from '../generated-artifacts/CreamBridge.json'; import * as CurveBridge from '../generated-artifacts/CurveBridge.json'; import * as DexForwarderBridge from '../generated-artifacts/DexForwarderBridge.json'; import * as DydxBridge from '../generated-artifacts/DydxBridge.json'; @@ -70,6 +71,7 @@ export const artifacts = { BalancerBridge: BalancerBridge as ContractArtifact, BancorBridge: BancorBridge as ContractArtifact, ChaiBridge: ChaiBridge as ContractArtifact, + CreamBridge: CreamBridge as ContractArtifact, CurveBridge: CurveBridge as ContractArtifact, DexForwarderBridge: DexForwarderBridge as ContractArtifact, DydxBridge: DydxBridge as ContractArtifact, diff --git a/contracts/asset-proxy/src/wrappers.ts b/contracts/asset-proxy/src/wrappers.ts index 8107eaf766..f9220bab2d 100644 --- a/contracts/asset-proxy/src/wrappers.ts +++ b/contracts/asset-proxy/src/wrappers.ts @@ -6,6 +6,7 @@ export * from '../generated-wrappers/balancer_bridge'; export * from '../generated-wrappers/bancor_bridge'; export * from '../generated-wrappers/chai_bridge'; +export * from '../generated-wrappers/cream_bridge'; export * from '../generated-wrappers/curve_bridge'; export * from '../generated-wrappers/dex_forwarder_bridge'; export * from '../generated-wrappers/dydx_bridge'; diff --git a/contracts/asset-proxy/test/artifacts.ts b/contracts/asset-proxy/test/artifacts.ts index aa01f1dc52..85c941cd6f 100644 --- a/contracts/asset-proxy/test/artifacts.ts +++ b/contracts/asset-proxy/test/artifacts.ts @@ -8,6 +8,7 @@ import { ContractArtifact } from 'ethereum-types'; import * as BalancerBridge from '../test/generated-artifacts/BalancerBridge.json'; import * as BancorBridge from '../test/generated-artifacts/BancorBridge.json'; import * as ChaiBridge from '../test/generated-artifacts/ChaiBridge.json'; +import * as CreamBridge from '../test/generated-artifacts/CreamBridge.json'; import * as CurveBridge from '../test/generated-artifacts/CurveBridge.json'; import * as DexForwarderBridge from '../test/generated-artifacts/DexForwarderBridge.json'; import * as DydxBridge from '../test/generated-artifacts/DydxBridge.json'; @@ -70,6 +71,7 @@ export const artifacts = { BalancerBridge: BalancerBridge as ContractArtifact, BancorBridge: BancorBridge as ContractArtifact, ChaiBridge: ChaiBridge as ContractArtifact, + CreamBridge: CreamBridge as ContractArtifact, CurveBridge: CurveBridge as ContractArtifact, DexForwarderBridge: DexForwarderBridge as ContractArtifact, DydxBridge: DydxBridge as ContractArtifact, diff --git a/contracts/asset-proxy/test/wrappers.ts b/contracts/asset-proxy/test/wrappers.ts index 4ae6089533..bf2954ea01 100644 --- a/contracts/asset-proxy/test/wrappers.ts +++ b/contracts/asset-proxy/test/wrappers.ts @@ -6,6 +6,7 @@ export * from '../test/generated-wrappers/balancer_bridge'; export * from '../test/generated-wrappers/bancor_bridge'; export * from '../test/generated-wrappers/chai_bridge'; +export * from '../test/generated-wrappers/cream_bridge'; export * from '../test/generated-wrappers/curve_bridge'; export * from '../test/generated-wrappers/dex_forwarder_bridge'; export * from '../test/generated-wrappers/dydx_bridge'; diff --git a/contracts/asset-proxy/tsconfig.json b/contracts/asset-proxy/tsconfig.json index ccb4c12320..2e7053bee1 100644 --- a/contracts/asset-proxy/tsconfig.json +++ b/contracts/asset-proxy/tsconfig.json @@ -6,6 +6,7 @@ "generated-artifacts/BalancerBridge.json", "generated-artifacts/BancorBridge.json", "generated-artifacts/ChaiBridge.json", + "generated-artifacts/CreamBridge.json", "generated-artifacts/CurveBridge.json", "generated-artifacts/DexForwarderBridge.json", "generated-artifacts/DydxBridge.json", @@ -58,6 +59,7 @@ "test/generated-artifacts/BalancerBridge.json", "test/generated-artifacts/BancorBridge.json", "test/generated-artifacts/ChaiBridge.json", + "test/generated-artifacts/CreamBridge.json", "test/generated-artifacts/CurveBridge.json", "test/generated-artifacts/DexForwarderBridge.json", "test/generated-artifacts/DydxBridge.json", From a97342a594b18823a8a76c73dab14f2e981fb509 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Tue, 29 Sep 2020 13:06:36 -0700 Subject: [PATCH 02/10] updated changelog --- contracts/asset-proxy/CHANGELOG.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index 61ddbe1aaa..3c85a4d4a2 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -25,6 +25,10 @@ { "note": "Reworked `KyberBridge`", "pr": 2683 + }, + { + "note": "Added `CreamBridge`", + "pr": 2715 } ] }, From c72aa653e8840bd1d5a4158ad576ab95def3599e Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Tue, 13 Oct 2020 20:27:08 -0700 Subject: [PATCH 03/10] Integrated CREAM into asset-swapper --- contracts/zero-ex/CHANGELOG.json | 4 + .../transformers/bridges/BridgeAdapter.sol | 8 ++ .../bridges/mixins/MixinAdapterAddresses.sol | 1 + .../fill_quote_transformer_test.ts | 1 + packages/asset-swapper/package.json | 1 + .../market_operation_utils/cream_utils.ts | 104 ++++++++++++++++++ .../src/utils/market_operation_utils/index.ts | 56 +++++++++- .../utils/market_operation_utils/sampler.ts | 4 +- .../sampler_operations.ts | 77 +++++++++++++ .../src/utils/market_operation_utils/types.ts | 5 + .../asset-swapper/test/dex_sampler_test.ts | 1 + .../test/market_operation_utils_test.ts | 93 ++++++++++++++++ packages/migrations/src/migration.ts | 1 + yarn.lock | 8 ++ 14 files changed, 357 insertions(+), 7 deletions(-) create mode 100644 packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts diff --git a/contracts/zero-ex/CHANGELOG.json b/contracts/zero-ex/CHANGELOG.json index 2bf7c0f902..56153459ab 100644 --- a/contracts/zero-ex/CHANGELOG.json +++ b/contracts/zero-ex/CHANGELOG.json @@ -65,6 +65,10 @@ { "note": "Added `Shell` into FQT", "pr": 2722 + }, + { + "note": "Added `CREAM` into FQT", + "pr": 2715 } ] }, diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol index 761ec15da1..3c60a8f436 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol @@ -46,6 +46,7 @@ contract BridgeAdapter is { address private immutable BALANCER_BRIDGE_ADDRESS; + address private immutable CREAM_BRIDGE_ADDRESS; address private immutable CURVE_BRIDGE_ADDRESS; address private immutable KYBER_BRIDGE_ADDRESS; address private immutable MOONISWAP_BRIDGE_ADDRESS; @@ -93,6 +94,7 @@ contract BridgeAdapter is SHELL_BRIDGE_ADDRESS = addresses.shellBridge; UNISWAP_BRIDGE_ADDRESS = addresses.uniswapBridge; UNISWAP_V2_BRIDGE_ADDRESS = addresses.uniswapV2Bridge; + CREAM_BRIDGE_ADDRESS = addresses.creamBridge; } function trade( @@ -170,6 +172,12 @@ contract BridgeAdapter is sellAmount, bridgeData ); + } else if (bridgeAddress == CREAM_BRIDGE_ADDRESS) { + boughtAmount = _tradeBalancer( + buyToken, + sellAmount, + bridgeData + ); } else { boughtAmount = _tradeZeroExBridge( bridgeAddress, diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinAdapterAddresses.sol b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinAdapterAddresses.sol index c9d13f5731..33e2de618d 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinAdapterAddresses.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/mixins/MixinAdapterAddresses.sol @@ -24,6 +24,7 @@ contract MixinAdapterAddresses struct AdapterAddresses { // Bridges address balancerBridge; + address creamBridge; address curveBridge; address kyberBridge; address mooniswapBridge; diff --git a/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts b/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts index fbeffdf643..724688da44 100644 --- a/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts +++ b/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts @@ -75,6 +75,7 @@ blockchainTests.resets('FillQuoteTransformer', env => { weth: NULL_ADDRESS, shellBridge: NULL_ADDRESS, shell: NULL_ADDRESS, + creamBridge: NULL_ADDRESS, }, ); transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync( diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index 8673709871..21aae41755 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -73,6 +73,7 @@ "@bancor/sdk": "^0.2.9", "axios": "^0.19.2", "axios-mock-adapter": "^1.18.1", + "cream-sor": "^0.3.3", "decimal.js": "^10.2.0", "ethereum-types": "^3.2.0", "ethereumjs-util": "^5.1.1", diff --git a/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts b/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts new file mode 100644 index 0000000000..f263270de3 --- /dev/null +++ b/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts @@ -0,0 +1,104 @@ +import { getPoolsWithTokens, parsePoolData } from 'cream-sor'; + +import { BalancerPool } from './balancer_utils'; + +// tslint:disable:boolean-naming + +interface CacheValue { + timestamp: number; + pools: BalancerPool[]; +} + +// tslint:disable:custom-no-magic-numbers +const FIVE_SECONDS_MS = 5 * 1000; +const ONE_DAY_MS = 24 * 60 * 60 * 1000; +const DEFAULT_TIMEOUT_MS = 1000; +const MAX_POOLS_FETCHED = 3; +// tslint:enable:custom-no-magic-numbers + +export class CreamPoolsCache { + constructor( + private readonly _cache: { [key: string]: CacheValue } = {}, + private readonly maxPoolsFetched: number = MAX_POOLS_FETCHED, + ) {} + + public async getPoolsForPairAsync( + takerToken: string, + makerToken: string, + timeoutMs: number = DEFAULT_TIMEOUT_MS, + ): Promise { + const timeout = new Promise(resolve => setTimeout(resolve, timeoutMs, [])); + return Promise.race([this._getPoolsForPairAsync(takerToken, makerToken), timeout]); + } + + public getCachedPoolAddressesForPair( + takerToken: string, + makerToken: string, + cacheExpiryMs?: number, + ): string[] | undefined { + const key = JSON.stringify([takerToken, makerToken]); + const value = this._cache[key]; + if (cacheExpiryMs === undefined) { + return value === undefined ? [] : value.pools.map(pool => pool.id); + } + const minTimestamp = Date.now() - cacheExpiryMs; + if (value === undefined || value.timestamp < minTimestamp) { + return undefined; + } else { + return value.pools.map(pool => pool.id); + } + } + + public howToSampleCream( + takerToken: string, + makerToken: string, + isAllowedSource: boolean, + ): { onChain: boolean; offChain: boolean } { + // If Balancer is excluded as a source, do not sample. + if (!isAllowedSource) { + return { onChain: false, offChain: false }; + } + const cachedCreamPools = this.getCachedPoolAddressesForPair(takerToken, makerToken, ONE_DAY_MS); + // Sample CREAM on-chain (i.e. via the ERC20BridgeSampler contract) if: + // - Cached values are not stale + // - There is at least one CREAM pool for this pair + const onChain = cachedCreamPools !== undefined && cachedCreamPools.length > 0; + // Sample Balancer off-chain (i.e. via GraphQL query + `computeCreamBuy/SellQuote`) + // if cached values are stale + const offChain = cachedCreamPools === undefined; + return { onChain, offChain }; + } + + protected async _getPoolsForPairAsync( + takerToken: string, + makerToken: string, + cacheExpiryMs: number = FIVE_SECONDS_MS, + ): Promise { + const key = JSON.stringify([takerToken, makerToken]); + const value = this._cache[key]; + const minTimestamp = Date.now() - cacheExpiryMs; + if (value === undefined || value.timestamp < minTimestamp) { + const pools = await this._fetchPoolsForPairAsync(takerToken, makerToken); + const timestamp = Date.now(); + this._cache[key] = { + pools, + timestamp, + }; + } + return this._cache[key].pools; + } + + // tslint:disable-next-line:prefer-function-over-method + protected async _fetchPoolsForPairAsync(takerToken: string, makerToken: string): Promise { + try { + const poolData = (await getPoolsWithTokens(takerToken, makerToken)).pools; + // Sort by maker token balance (descending) + const pools = parsePoolData(poolData, takerToken, makerToken).sort((a, b) => + b.balanceOut.minus(a.balanceOut).toNumber(), + ); + return pools.length > this.maxPoolsFetched ? pools.slice(0, this.maxPoolsFetched) : pools; + } catch (err) { + return []; + } + } +} diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 58fcf395c5..145527804f 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -150,6 +150,23 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer), ); + const { + onChain: sampleCreamOnChain, + offChain: sampleCreamOffChain, + } = this._sampler.creamPoolsCache.howToSampleCream( + takerToken, + makerToken, + quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), + ); + + let excludedSources: ERC20BridgeSource[] = []; + if (!sampleCreamOnChain) { + excludedSources = excludedSources.concat(ERC20BridgeSource.Cream); + } + if (!sampleBalancerOnChain) { + excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer); + } + // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( // Get native order fillable amounts. @@ -176,7 +193,7 @@ export class MarketOperationUtils { ), // Get sell quotes for taker -> maker. this._sampler.getSellQuotes( - quoteSourceFilters.exclude(sampleBalancerOnChain ? [] : ERC20BridgeSource.Balancer).sources, + quoteSourceFilters.exclude(excludedSources).sources, makerToken, takerToken, sampleAmounts, @@ -209,6 +226,10 @@ export class MarketOperationUtils { ? this._sampler.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts) : Promise.resolve([]); + const offChainCreamPromise = sampleCreamOffChain + ? this._sampler.getCreamSellQuotesOffChainAsync(makerToken, takerToken, sampleAmounts) + : Promise.resolve([]); + const offChainBancorPromise = quoteSourceFilters.isAllowed(ERC20BridgeSource.Bancor) ? this._sampler.getBancorSellQuotesOffChainAsync(makerToken, takerToken, [takerAmount]) : Promise.resolve([]); @@ -217,15 +238,16 @@ export class MarketOperationUtils { [orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes], rfqtIndicativeQuotes, offChainBalancerQuotes, + offChainCreamQuotes, offChainBancorQuotes, - ] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainBancorPromise]); + ] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise, offChainBancorPromise]); return { side: MarketOperation.Sell, inputAmount: takerAmount, inputToken: takerToken, outputToken: makerToken, - dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, offChainBancorQuotes]), + dexQuotes: dexQuotes.concat([...offChainBalancerQuotes, ...offChainCreamQuotes, offChainBancorQuotes]), nativeOrders, orderFillableAmounts, ethToOutputRate: ethToMakerAssetRate, @@ -266,6 +288,23 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Balancer), ); + const { + onChain: sampleCreamOnChain, + offChain: sampleCreamOffChain, + } = this._sampler.creamPoolsCache.howToSampleCream( + takerToken, + makerToken, + quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), + ); + + let excludedSources: ERC20BridgeSource[] = []; + if (!sampleCreamOnChain) { + excludedSources = excludedSources.concat(ERC20BridgeSource.Cream); + } + if (!sampleBalancerOnChain) { + excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer); + } + // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( // Get native order fillable amounts. @@ -292,7 +331,7 @@ export class MarketOperationUtils { ), // Get buy quotes for taker -> maker. this._sampler.getBuyQuotes( - quoteSourceFilters.exclude(sampleBalancerOnChain ? [] : ERC20BridgeSource.Balancer).sources, + quoteSourceFilters.exclude(excludedSources).sources, makerToken, takerToken, sampleAmounts, @@ -324,11 +363,16 @@ export class MarketOperationUtils { ? this._sampler.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, sampleAmounts) : Promise.resolve([]); + const offChainCreamPromise = sampleCreamOffChain + ? this._sampler.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, sampleAmounts) + : Promise.resolve([]); + const [ [orderFillableAmounts, ethToMakerAssetRate, ethToTakerAssetRate, dexQuotes, twoHopQuotes], rfqtIndicativeQuotes, offChainBalancerQuotes, - ] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise]); + offChainCreamQuotes, + ] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise]); // Attach the MultiBridge address to the sample fillData (dexQuotes.find(quotes => quotes[0] && quotes[0].source === ERC20BridgeSource.MultiBridge) || []).forEach( q => (q.fillData = { poolAddress: this._multiBridge }), @@ -338,7 +382,7 @@ export class MarketOperationUtils { inputAmount: makerAmount, inputToken: makerToken, outputToken: takerToken, - dexQuotes: dexQuotes.concat(offChainBalancerQuotes), + dexQuotes: dexQuotes.concat(offChainBalancerQuotes, offChainCreamQuotes), nativeOrders, orderFillableAmounts, ethToOutputRate: ethToTakerAssetRate, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts index d17bbd6831..5c6f0cc1db 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts @@ -6,6 +6,7 @@ import { ERC20BridgeSamplerContract } from '../../wrappers'; import { BalancerPoolsCache } from './balancer_utils'; import { BancorService } from './bancor_service'; +import { CreamPoolsCache } from './cream_utils'; import { SamplerOperations } from './sampler_operations'; import { BatchedOperation } from './types'; @@ -37,9 +38,10 @@ export class DexOrderSampler extends SamplerOperations { private readonly _samplerOverrides?: SamplerOverrides, provider?: SupportedProvider, balancerPoolsCache?: BalancerPoolsCache, + creamPoolsCache?: CreamPoolsCache, getBancorServiceFn?: () => BancorService, ) { - super(_samplerContract, provider, balancerPoolsCache, getBancorServiceFn); + super(_samplerContract, provider, balancerPoolsCache, creamPoolsCache, getBancorServiceFn); } /* Type overloads for `executeAsync()`. Could skip this if we would upgrade TS. */ diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index 1ecf83e7a0..70f4d58a77 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -8,6 +8,7 @@ import { ERC20BridgeSamplerContract } from '../../wrappers'; import { BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils'; import { BancorService } from './bancor_service'; import { MAINNET_SUSHI_SWAP_ROUTER, MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants'; +import { CreamPoolsCache } from './cream_utils'; import { getCurveInfosForPair, getSwerveInfosForPair } from './curve_utils'; import { getKyberReserveIdsForPair } from './kyber_utils'; import { getMultiBridgeIntermediateToken } from './multibridge_utils'; @@ -18,6 +19,7 @@ import { BalancerFillData, BancorFillData, BatchedOperation, + CreamFillData, CurveFillData, CurveInfo, DexSample, @@ -72,6 +74,7 @@ export class SamplerOperations { protected readonly _samplerContract: ERC20BridgeSamplerContract, public readonly provider?: SupportedProvider, public readonly balancerPoolsCache: BalancerPoolsCache = new BalancerPoolsCache(), + public readonly creamPoolsCache: CreamPoolsCache = new CreamPoolsCache(), protected readonly getBancorServiceFn?: () => BancorService, // for dependency injection in tests ) {} @@ -466,6 +469,68 @@ export class SamplerOperations { ); } + public getCreamSellQuotes( + poolAddress: string, + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ): SourceQuoteOperation { + return new SamplerContractOperation({ + source: ERC20BridgeSource.Cream, + fillData: { poolAddress }, + contract: this._samplerContract, + function: this._samplerContract.sampleSellsFromBalancer, + params: [poolAddress, takerToken, makerToken, takerFillAmounts], + }); + } + + public getCreamBuyQuotes( + poolAddress: string, + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ): SourceQuoteOperation { + return new SamplerContractOperation({ + source: ERC20BridgeSource.Cream, + fillData: { poolAddress }, + contract: this._samplerContract, + function: this._samplerContract.sampleBuysFromBalancer, + params: [poolAddress, takerToken, makerToken, makerFillAmounts], + }); + } + + public async getCreamSellQuotesOffChainAsync( + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ): Promise>>> { + const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); + return pools.map(pool => + takerFillAmounts.map(amount => ({ + source: ERC20BridgeSource.Balancer, + output: computeBalancerSellQuote(pool, amount), + input: amount, + fillData: { poolAddress: pool.id }, + })), + ); + } + + public async getCreamBuyQuotesOffChainAsync( + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ): Promise>>> { + const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); + return pools.map(pool => + makerFillAmounts.map(amount => ({ + source: ERC20BridgeSource.Balancer, + output: computeBalancerBuyQuote(pool, amount), + input: amount, + fillData: { poolAddress: pool.id }, + })), + ); + } + public getMStableSellQuotes( makerToken: string, takerToken: string, @@ -997,6 +1062,12 @@ export class SamplerOperations { .map(poolAddress => this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), ); + case ERC20BridgeSource.Cream: + return this.creamPoolsCache + .getCachedPoolAddressesForPair(takerToken, makerToken)! + .map(poolAddress => + this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), + ); case ERC20BridgeSource.Shell: return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts); default: @@ -1086,6 +1157,12 @@ export class SamplerOperations { .map(poolAddress => this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), ); + case ERC20BridgeSource.Cream: + return this.creamPoolsCache + .getCachedPoolAddressesForPair(takerToken, makerToken)! + .map(poolAddress => + this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), + ); case ERC20BridgeSource.Shell: return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts); default: diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index 0afc145d47..68c178d174 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -37,6 +37,7 @@ export enum ERC20BridgeSource { LiquidityProvider = 'LiquidityProvider', MultiBridge = 'MultiBridge', Balancer = 'Balancer', + Cream = 'CREAM', Bancor = 'Bancor', MStable = 'mStable', Mooniswap = 'Mooniswap', @@ -103,6 +104,10 @@ export interface BalancerFillData extends FillData { poolAddress: string; } +export interface CreamFillData extends FillData { + poolAddress: string; +} + export interface UniswapV2FillData extends FillData { tokenAddressPath: string[]; } diff --git a/packages/asset-swapper/test/dex_sampler_test.ts b/packages/asset-swapper/test/dex_sampler_test.ts index b267e0d170..8d2706b0e3 100644 --- a/packages/asset-swapper/test/dex_sampler_test.ts +++ b/packages/asset-swapper/test/dex_sampler_test.ts @@ -504,6 +504,7 @@ describe('DexSampler tests', () => { undefined, // sampler overrides provider, undefined, // balancer cache + undefined, // cream cache () => bancorService, ); const quotes = await dexOrderSampler.getBancorSellQuotesOffChainAsync( diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index facd6aebda..10e1e6455b 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -25,6 +25,7 @@ import { SOURCE_FLAGS, ZERO_AMOUNT, } from '../src/utils/market_operation_utils/constants'; +import { CreamPoolsCache } from '../src/utils/market_operation_utils/cream_utils'; import { createFills } from '../src/utils/market_operation_utils/fills'; import { DexOrderSampler } from '../src/utils/market_operation_utils/sampler'; import { BATCH_SOURCE_FILTERS } from '../src/utils/market_operation_utils/sampler_operations'; @@ -51,6 +52,7 @@ const DEFAULT_EXCLUDED = [ ERC20BridgeSource.SushiSwap, ERC20BridgeSource.MultiHop, ERC20BridgeSource.Shell, + ERC20BridgeSource.Cream, ]; const BUY_SOURCES = BUY_SOURCE_FILTER.sources; const SELL_SOURCES = SELL_SOURCE_FILTER.sources; @@ -288,6 +290,7 @@ describe('MarketOperationUtils tests', () => { [ERC20BridgeSource.SushiSwap]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.MultiHop]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.Shell]: _.times(NUM_SAMPLES, () => 0), + [ERC20BridgeSource.Cream]: _.times(NUM_SAMPLES, () => 0), }; const DEFAULT_RATES: RatesBySource = { @@ -334,6 +337,7 @@ describe('MarketOperationUtils tests', () => { [ERC20BridgeSource.Native]: { order: createOrder() }, [ERC20BridgeSource.MultiHop]: {}, [ERC20BridgeSource.Shell]: {}, + [ERC20BridgeSource.Cream]: { poolAddress: randomAddress() }, }; const DEFAULT_OPS = { @@ -370,6 +374,30 @@ describe('MarketOperationUtils tests', () => { DEFAULT_FILL_DATA[ERC20BridgeSource.Balancer], ), ], + getCreamSellQuotesOffChainAsync: ( + _makerToken: string, + _takerToken: string, + takerFillAmounts: BigNumber[], + ) => [ + createSamplesFromRates( + ERC20BridgeSource.Cream, + takerFillAmounts, + createDecreasingRates(takerFillAmounts.length), + DEFAULT_FILL_DATA[ERC20BridgeSource.Cream], + ), + ], + getCreamBuyQuotesOffChainAsync: ( + _makerToken: string, + _takerToken: string, + makerFillAmounts: BigNumber[], + ) => [ + createSamplesFromRates( + ERC20BridgeSource.Cream, + makerFillAmounts, + createDecreasingRates(makerFillAmounts.length).map(r => new BigNumber(1).div(r)), + DEFAULT_FILL_DATA[ERC20BridgeSource.Cream], + ), + ], getBancorSellQuotesOffChainAsync: (_makerToken: string, _takerToken: string, takerFillAmounts: BigNumber[]) => createSamplesFromRates( ERC20BridgeSource.Bancor, @@ -389,6 +417,7 @@ describe('MarketOperationUtils tests', () => { return ops; }, balancerPoolsCache: new BalancerPoolsCache(), + creamPoolsCache: new CreamPoolsCache(), } as any) as DexOrderSampler; function replaceSamplerOps(ops: Partial = {}): void { @@ -492,6 +521,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); }, + getCreamSellQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); + }, }); await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, @@ -522,6 +559,14 @@ describe('MarketOperationUtils tests', () => { args.sources = args.sources.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); }, + getCreamSellQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ) => { + args.sources = args.sources.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); + }, }); const registryAddress = randomAddress(); const newMarketOperationUtils = new MarketOperationUtils( @@ -563,6 +608,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); }, + getCreamSellQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); + }, }); await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, @@ -594,6 +647,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); }, + getCreamSellQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + takerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamSellQuotesOffChainAsync(makerToken, takerToken, takerFillAmounts); + }, }); await marketOperationUtils.getMarketSellOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, @@ -984,6 +1045,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); }, + getCreamBuyQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); + }, }); await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, @@ -1014,6 +1083,14 @@ describe('MarketOperationUtils tests', () => { args.sources = args.sources.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); }, + getCreamBuyQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ) => { + args.sources = args.sources.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); + }, }); const registryAddress = randomAddress(); const newMarketOperationUtils = new MarketOperationUtils( @@ -1055,6 +1132,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); }, + getCreamBuyQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); + }, }); await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, @@ -1086,6 +1171,14 @@ describe('MarketOperationUtils tests', () => { sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Balancer); return DEFAULT_OPS.getBalancerBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); }, + getCreamBuyQuotesOffChainAsync: ( + makerToken: string, + takerToken: string, + makerFillAmounts: BigNumber[], + ) => { + sourcesPolled = sourcesPolled.concat(ERC20BridgeSource.Cream); + return DEFAULT_OPS.getCreamBuyQuotesOffChainAsync(makerToken, takerToken, makerFillAmounts); + }, }); await marketOperationUtils.getMarketBuyOrdersAsync(ORDERS, FILL_AMOUNT, { ...DEFAULT_OPTS, diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 8c96994fba..bdc487dada 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -325,6 +325,7 @@ export async function runMigrationsAsync( uniswapExchangeFactory: NULL_ADDRESS, mStable: NULL_ADDRESS, shellBridge: NULL_ADDRESS, + creamBridge: NULL_ADDRESS, shell: NULL_ADDRESS, weth: etherToken.address, }, diff --git a/yarn.lock b/yarn.lock index f5a89efc2b..7c3a875798 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5510,6 +5510,14 @@ coveralls@^3.0.0: minimist "^1.2.0" request "^2.79.0" +cream-sor@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/cream-sor/-/cream-sor-0.3.3.tgz#ae7ab50c68cfd36a89e2101187ceebbb79e1b14c" + integrity sha512-taQSvCUunPhwyebwbjxh1l9NDp39lsre+Q2oRMK+gqzbu+Wlbg5GAquwoV2/GLgzia70gi4x1rJCJsUmc5Kygg== + dependencies: + bignumber.js "^9.0.0" + isomorphic-fetch "^2.2.1" + create-ecdh@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.1.tgz#44223dfed533193ba5ba54e0df5709b89acf1f82" From 4803e2f68c9e8a56b77de9e5c1a7f80524357f98 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Wed, 14 Oct 2020 09:56:23 -0700 Subject: [PATCH 04/10] Add peer dependencies for cream-sor, small fix to sampler routing --- packages/asset-swapper/package.json | 4 + .../sampler_operations.ts | 4 +- yarn.lock | 259 ++++++++++++++++++ 3 files changed, 265 insertions(+), 2 deletions(-) diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index b3de791fc3..bce6d04b7f 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -71,6 +71,10 @@ "@0x/web3-wrapper": "^7.2.0", "@balancer-labs/sor": "0.3.2", "@bancor/sdk": "^0.2.9", + "@ethersproject/abi": "^5.0.1", + "@ethersproject/address": "^5.0.1", + "@ethersproject/contracts": "^5.0.1", + "@ethersproject/providers": "^5.0.4", "axios": "^0.19.2", "axios-mock-adapter": "^1.18.1", "cream-sor": "^0.3.3", diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index db00313a40..bb37e24a60 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -508,7 +508,7 @@ export class SamplerOperations { const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); return pools.map(pool => takerFillAmounts.map(amount => ({ - source: ERC20BridgeSource.Balancer, + source: ERC20BridgeSource.Cream, output: computeBalancerSellQuote(pool, amount), input: amount, fillData: { poolAddress: pool.id }, @@ -524,7 +524,7 @@ export class SamplerOperations { const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); return pools.map(pool => makerFillAmounts.map(amount => ({ - source: ERC20BridgeSource.Balancer, + source: ERC20BridgeSource.Cream, output: computeBalancerBuyQuote(pool, amount), input: amount, fillData: { poolAddress: pool.id }, diff --git a/yarn.lock b/yarn.lock index 7c3a875798..c98c05e5d2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1093,6 +1093,242 @@ version "0.7.2" resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.2.tgz#b180097bb44a40c3b59efea9cf28df2fe542d518" +"@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.5": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.7.tgz#79e52452bd3ca2956d0e1c964207a58ad1a0ee7b" + integrity sha512-Cqktk+hSIckwP/W8O47Eef60VwmoSC/L3lY0+dIBhQPCNn9E4V7rwmm2aFrNRRDJfFlGuZ1khkQUOc3oBX+niw== + dependencies: + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/hash" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + +"@ethersproject/abstract-provider@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.0.5.tgz#797a32a8707830af1ad8f833e9c228994d5572b9" + integrity sha512-i/CjElAkzV7vQBAeoz+IpjGfcFYEP9eD7j3fzZ0fzTq03DO7PPnR+xkEZ1IoDXGwDS+55aLM1xvLDwB/Lx6IOQ== + dependencies: + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/networks" "^5.0.3" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/transactions" "^5.0.5" + "@ethersproject/web" "^5.0.6" + +"@ethersproject/abstract-signer@^5.0.4": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.0.6.tgz#c01211665ab9c9e93988c4783b789712fd93a388" + integrity sha512-h8TZBX3pL2Xx9tmsRxfWcaaI+FcJFHWvZ/vNvFjLp8zJ0kPD501LKTt2jo44LZ20N3EW68JMoyEmRQ6bpsn+iA== + dependencies: + "@ethersproject/abstract-provider" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + +"@ethersproject/address@^5.0.1", "@ethersproject/address@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.5.tgz#2caa65f6b7125015395b1b54c985ee0b27059cc7" + integrity sha512-DpkQ6rwk9jTefrRsJzEm6nhRiJd9pvhn1xN0rw5N/jswXG5r7BLk/GVA0mMAVWAsYfvi2xSc5L41FMox43RYEA== + dependencies: + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/rlp" "^5.0.3" + bn.js "^4.4.0" + +"@ethersproject/base64@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.0.4.tgz#b0d8fdbf3dda977cf546dcd35725a7b1d5256caa" + integrity sha512-4KRykQ7BQMeOXfvio1YITwHjxwBzh92UoXIdzxDE1p53CK28bbHPdsPNYo0wl0El7lJAMpT2SOdL0hhbWRnyIA== + dependencies: + "@ethersproject/bytes" "^5.0.4" + +"@ethersproject/basex@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.0.4.tgz#93e1cd11f9a47281da2389de24f88e13e9d90847" + integrity sha512-ixIr/kKiAoSzOnSc777AGIOAhKai5Ivqr4HO/Gz+YG+xkfv6kqD6AW4ga9vM20Wwb0QBhh3LoRWTu4V1K+x9Ew== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/properties" "^5.0.3" + +"@ethersproject/bignumber@^5.0.7": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.8.tgz#cee33bd8eb0266176def0d371b45274b1d2c4ec0" + integrity sha512-KXFVAFKS1jdTXYN8BE5Oj+ZfPMh28iRdFeNGBVT6cUFdtiPVqeXqc0ggvBqA3A1VoFFGgM7oAeaagA393aORHA== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + bn.js "^4.4.0" + +"@ethersproject/bytes@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.5.tgz#688b70000e550de0c97a151a21f15b87d7f97d7c" + integrity sha512-IEj9HpZB+ACS6cZ+QQMTqmu/cnUK2fYNE6ms/PVxjoBjoxc6HCraLpam1KuRvreMy0i523PLmjN8OYeikRdcUQ== + dependencies: + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/constants@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.5.tgz#0ed19b002e8404bdf6d135234dc86a7d9bcf9b71" + integrity sha512-foaQVmxp2+ik9FrLUCtVrLZCj4M3Ibgkqvh+Xw/vFRSerkjVSYePApaVE5essxhoSlF1U9oXfWY09QI2AXtgKA== + dependencies: + "@ethersproject/bignumber" "^5.0.7" + +"@ethersproject/contracts@^5.0.1": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.0.5.tgz#64831a341ec8ca225e83ff3e9437c26b970fd5d7" + integrity sha512-tFI255lFbmbqMkgnuyhDWHl3yWqttPlReplYuVvDCT/SuvBjLR4ad2uipBlh1fh5X1ipK9ettAoV4S0HKim4Kw== + dependencies: + "@ethersproject/abi" "^5.0.5" + "@ethersproject/abstract-provider" "^5.0.4" + "@ethersproject/abstract-signer" "^5.0.4" + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + +"@ethersproject/hash@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.5.tgz#e383ba2c7941834266fa6e2cf543d2b0c50a9d59" + integrity sha512-GpI80/h2HDpfNKpCZoxQJCjOQloGnlD5hM1G+tZe8FQDJhEvFjJoPDuWv+NaYjJfOciKS2Axqc4Q4WamdLoUgg== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/strings" "^5.0.4" + +"@ethersproject/keccak256@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.4.tgz#36ca0a7d1ae2a272da5654cb886776d0c680ef3a" + integrity sha512-GNpiOUm9PGUxFNqOxYKDQBM0u68bG9XC9iOulEQ8I0tOx/4qUpgVzvgXL6ugxr0RY554Gz/NQsVqknqPzUcxpQ== + dependencies: + "@ethersproject/bytes" "^5.0.4" + js-sha3 "0.5.7" + +"@ethersproject/logger@^5.0.5": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.6.tgz#faa484203e86e08be9e07fef826afeef7183fe88" + integrity sha512-FrX0Vnb3JZ1md/7GIZfmJ06XOAA8r3q9Uqt9O5orr4ZiksnbpXKlyDzQtlZ5Yv18RS8CAUbiKH9vwidJg1BPmQ== + +"@ethersproject/networks@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.0.4.tgz#6d320a5e15a0cda804f5da88be0ba846156f6eec" + integrity sha512-/wHDTRms5mpJ09BoDrbNdFWINzONe05wZRgohCXvEv39rrH/Gd/yAnct8wC0RsW3tmFOgjgQxuBvypIxuUynTw== + dependencies: + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/properties@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.4.tgz#a67a1f5a52c30850b5062c861631e73d131f666e" + integrity sha512-UdyX3GqBxFt15B0uSESdDNmhvEbK3ACdDXl2soshoPcneXuTswHDeA0LoPlnaZzhbgk4p6jqb4GMms5C26Qu6A== + dependencies: + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/providers@^5.0.4": + version "5.0.12" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.0.12.tgz#de05e865e130709ea1e0870511eb892bda7d41cb" + integrity sha512-bRUEVNth+wGlm2Q0cQprVlixBWumfP9anrgAc3V2CbIh+GKvCwisVO8uRLrZOfOvTNSy6PUJi/Z4D5L+k3NAog== + dependencies: + "@ethersproject/abstract-provider" "^5.0.4" + "@ethersproject/abstract-signer" "^5.0.4" + "@ethersproject/address" "^5.0.4" + "@ethersproject/basex" "^5.0.3" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/hash" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/networks" "^5.0.3" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/random" "^5.0.3" + "@ethersproject/rlp" "^5.0.3" + "@ethersproject/sha2" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + "@ethersproject/transactions" "^5.0.5" + "@ethersproject/web" "^5.0.6" + bech32 "1.1.4" + ws "7.2.3" + +"@ethersproject/random@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.0.4.tgz#98f7cf65b0e588cec39ef24843e391ed5004556f" + integrity sha512-AIZJhqs6Ba4/+U3lOjt3QZbP6b/kuuGLJUYFUonAgWmkTHwqsCwYnFvnHKQSUuHbXHvErp7WFXFlztx+yMn3kQ== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/rlp@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.0.4.tgz#0090a0271e84ea803016a112a79f5cfd80271a77" + integrity sha512-5qrrZad7VTjofxSsm7Zg/7Dr4ZOln4S2CqiDdOuTv6MBKnXj0CiBojXyuDy52M8O3wxH0CyE924hXWTDV1PQWQ== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/sha2@^5.0.3": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.0.4.tgz#40f639721a27dbe034b3dee021ba20b054586fec" + integrity sha512-0yFhf1mspxAfWdXXoPtK94adUeu1R7/FzAa+DfEiZTc76sz/vHXf0LSIazoR3znYKFny6haBxME+usbvvEcF3A== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + hash.js "1.1.3" + +"@ethersproject/signing-key@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.0.5.tgz#acfd06fc05a14180df7e027688bbd23fc4baf782" + integrity sha512-Z1wY7JC1HVO4CvQWY2TyTTuAr8xK3bJijZw1a9G92JEmKdv1j255R/0YLBBcFTl2J65LUjtXynNJ2GbArPGi5g== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + elliptic "6.5.3" + +"@ethersproject/strings@^5.0.4": + version "5.0.5" + resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.5.tgz#ed7e99a282a02f40757691b04a24cd83f3752195" + integrity sha512-JED6WaIV00xM/gvj8vSnd+0VWtDYdidTmavFRCTQakqfz+4tDo6Jz5LHgG+dd45h7ah7ykCHW0C7ZXWEDROCXQ== + dependencies: + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + +"@ethersproject/transactions@^5.0.5": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.6.tgz#b8b27938be6e9ed671dbdd35fe98af8b14d0df7c" + integrity sha512-htsFhOD+NMBxx676A8ehSuwVV49iqpSB+CkjPZ02tpNew0K6p8g0CZ46Z1ZP946gIHAU80xQ0NACHYrjIUaCFA== + dependencies: + "@ethersproject/address" "^5.0.4" + "@ethersproject/bignumber" "^5.0.7" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/constants" "^5.0.4" + "@ethersproject/keccak256" "^5.0.3" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/rlp" "^5.0.3" + "@ethersproject/signing-key" "^5.0.4" + +"@ethersproject/web@^5.0.6": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.0.9.tgz#b08f8295f4bfd4777c8723fe9572f5453b9f03cb" + integrity sha512-//QNlv1MSkOII1hv3+HQwWoiVFS+BMVGI0KYeUww4cyrEktnx1QIez5bTSab9s9fWTFaWKNmQNBwMbxAqPuYDw== + dependencies: + "@ethersproject/base64" "^5.0.3" + "@ethersproject/bytes" "^5.0.4" + "@ethersproject/logger" "^5.0.5" + "@ethersproject/properties" "^5.0.3" + "@ethersproject/strings" "^5.0.4" + "@evocateur/libnpmaccess@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845" @@ -3911,6 +4147,11 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bech32@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + before-after-hook@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" @@ -6364,6 +6605,19 @@ elliptic@6.5.2: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +elliptic@6.5.3: + version "6.5.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -18449,6 +18703,11 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" +ws@7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" + integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" From ef65aa5bf69ba4c829712502a5f494d16bd492d3 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Wed, 14 Oct 2020 11:37:03 -0700 Subject: [PATCH 05/10] further fixes in market operation utils --- .../src/utils/market_operation_utils/cream_utils.ts | 4 ++-- .../src/utils/market_operation_utils/sampler_operations.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts b/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts index f263270de3..a31e420b22 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/cream_utils.ts @@ -54,7 +54,7 @@ export class CreamPoolsCache { makerToken: string, isAllowedSource: boolean, ): { onChain: boolean; offChain: boolean } { - // If Balancer is excluded as a source, do not sample. + // If CREAM is excluded as a source, do not sample. if (!isAllowedSource) { return { onChain: false, offChain: false }; } @@ -63,7 +63,7 @@ export class CreamPoolsCache { // - Cached values are not stale // - There is at least one CREAM pool for this pair const onChain = cachedCreamPools !== undefined && cachedCreamPools.length > 0; - // Sample Balancer off-chain (i.e. via GraphQL query + `computeCreamBuy/SellQuote`) + // Sample CREAM off-chain (i.e. via GraphQL query + `computeCreamBuy/SellQuote`) // if cached values are stale const offChain = cachedCreamPools === undefined; return { onChain, offChain }; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index bb37e24a60..d877ca9c93 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -520,7 +520,7 @@ export class SamplerOperations { makerToken: string, takerToken: string, makerFillAmounts: BigNumber[], - ): Promise>>> { + ): Promise>>> { const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); return pools.map(pool => makerFillAmounts.map(amount => ({ @@ -1109,7 +1109,7 @@ export class SamplerOperations { return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), + this.getCreamSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), ); case ERC20BridgeSource.Shell: return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts); @@ -1206,7 +1206,7 @@ export class SamplerOperations { return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), + this.getCreamBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), ); case ERC20BridgeSource.Shell: return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts); From 7161bbe8363aceca44fc90278f676643af871dd8 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Wed, 14 Oct 2020 11:38:05 -0700 Subject: [PATCH 06/10] prettier --- .../src/utils/market_operation_utils/index.ts | 8 +++++++- .../test/market_operation_utils_test.ts | 12 ++---------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 145527804f..13c9089d7c 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -240,7 +240,13 @@ export class MarketOperationUtils { offChainBalancerQuotes, offChainCreamQuotes, offChainBancorQuotes, - ] = await Promise.all([samplerPromise, rfqtPromise, offChainBalancerPromise, offChainCreamPromise, offChainBancorPromise]); + ] = await Promise.all([ + samplerPromise, + rfqtPromise, + offChainBalancerPromise, + offChainCreamPromise, + offChainBancorPromise, + ]); return { side: MarketOperation.Sell, diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index 385421d550..8e54b748fa 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -373,11 +373,7 @@ describe('MarketOperationUtils tests', () => { DEFAULT_FILL_DATA[ERC20BridgeSource.Balancer], ), ], - getCreamSellQuotesOffChainAsync: ( - _makerToken: string, - _takerToken: string, - takerFillAmounts: BigNumber[], - ) => [ + getCreamSellQuotesOffChainAsync: (_makerToken: string, _takerToken: string, takerFillAmounts: BigNumber[]) => [ createSamplesFromRates( ERC20BridgeSource.Cream, takerFillAmounts, @@ -385,11 +381,7 @@ describe('MarketOperationUtils tests', () => { DEFAULT_FILL_DATA[ERC20BridgeSource.Cream], ), ], - getCreamBuyQuotesOffChainAsync: ( - _makerToken: string, - _takerToken: string, - makerFillAmounts: BigNumber[], - ) => [ + getCreamBuyQuotesOffChainAsync: (_makerToken: string, _takerToken: string, makerFillAmounts: BigNumber[]) => [ createSamplesFromRates( ERC20BridgeSource.Cream, makerFillAmounts, From bbfa9c34abbc78b2e0aa872b6c4cde36ebc45c08 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Wed, 14 Oct 2020 12:42:06 -0700 Subject: [PATCH 07/10] Add CREAM to market operation utils constants :facepalm: --- packages/asset-swapper/src/index.ts | 1 + .../src/utils/market_operation_utils/constants.ts | 2 ++ .../src/utils/market_operation_utils/orders.ts | 11 +++++++++++ 3 files changed, 14 insertions(+) diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts index 0c87279cc8..a6ce6ff596 100644 --- a/packages/asset-swapper/src/index.ts +++ b/packages/asset-swapper/src/index.ts @@ -132,6 +132,7 @@ export { CurveFillData, CurveFunctionSelectors, CurveInfo, + CreamFillData, DexSample, DODOFillData, ERC20BridgeSource, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index 790f083c03..d3a6bb7c60 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -25,6 +25,7 @@ export const SELL_SOURCE_FILTER = new SourceFilters([ ERC20BridgeSource.Shell, ERC20BridgeSource.MultiHop, ERC20BridgeSource.Dodo, + ERC20BridgeSource.Cream, ]); /** @@ -47,6 +48,7 @@ export const BUY_SOURCE_FILTER = new SourceFilters( ERC20BridgeSource.SushiSwap, ERC20BridgeSource.MultiHop, ERC20BridgeSource.Dodo, + ERC20BridgeSource.Cream, ], [ERC20BridgeSource.MultiBridge], ); diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index e08353d8d7..d12f0e1dea 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -22,6 +22,7 @@ import { BalancerFillData, BancorFillData, CollapsedFill, + CreamFillData, CurveFillData, DexSample, DODOFillData, @@ -177,6 +178,8 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath return opts.contractAddresses.bancorBridge; case ERC20BridgeSource.Balancer: return opts.contractAddresses.balancerBridge; + case ERC20BridgeSource.Cream: + return opts.contractAddresses.balancerBridge; case ERC20BridgeSource.LiquidityProvider: return (fill.fillData as LiquidityProviderFillData).poolAddress; case ERC20BridgeSource.MultiBridge: @@ -241,6 +244,14 @@ export function createBridgeOrder( createBalancerBridgeData(takerToken, balancerFillData.poolAddress), ); break; + case ERC20BridgeSource.Cream: + const creamFillData = (fill as CollapsedFill).fillData!; // tslint:disable-line:no-non-null-assertion + makerAssetData = assetDataUtils.encodeERC20BridgeAssetData( + makerToken, + bridgeAddress, + createBalancerBridgeData(takerToken, creamFillData.poolAddress), + ); + break; case ERC20BridgeSource.Bancor: const bancorFillData = (fill as CollapsedFill).fillData!; // tslint:disable-line:no-non-null-assertion makerAssetData = assetDataUtils.encodeERC20BridgeAssetData( From 07ab10b00050507bfaa59db33a3a492f536cb6fd Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Thu, 15 Oct 2020 16:58:39 -0700 Subject: [PATCH 08/10] Deployed CreamBridge, refactor to simplify code --- .../transformers/bridges/BridgeAdapter.sol | 8 +-- packages/asset-swapper/src/index.ts | 1 - .../src/utils/market_operation_utils/index.ts | 22 +++------ .../utils/market_operation_utils/orders.ts | 5 +- .../sampler_operations.ts | 49 ++++--------------- .../src/utils/market_operation_utils/types.ts | 4 -- packages/contract-addresses/CHANGELOG.json | 4 ++ packages/contract-addresses/addresses.json | 5 ++ packages/contract-addresses/src/index.ts | 1 + 9 files changed, 31 insertions(+), 68 deletions(-) diff --git a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol index 3c60a8f436..bedd77c898 100644 --- a/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol +++ b/contracts/zero-ex/contracts/src/transformers/bridges/BridgeAdapter.sol @@ -136,7 +136,7 @@ contract BridgeAdapter is sellAmount, bridgeData ); - } else if (bridgeAddress == BALANCER_BRIDGE_ADDRESS) { + } else if (bridgeAddress == BALANCER_BRIDGE_ADDRESS || bridgeAddress == CREAM_BRIDGE_ADDRESS) { boughtAmount = _tradeBalancer( buyToken, sellAmount, @@ -172,12 +172,6 @@ contract BridgeAdapter is sellAmount, bridgeData ); - } else if (bridgeAddress == CREAM_BRIDGE_ADDRESS) { - boughtAmount = _tradeBalancer( - buyToken, - sellAmount, - bridgeData - ); } else { boughtAmount = _tradeZeroExBridge( bridgeAddress, diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts index a6ce6ff596..0c87279cc8 100644 --- a/packages/asset-swapper/src/index.ts +++ b/packages/asset-swapper/src/index.ts @@ -132,7 +132,6 @@ export { CurveFillData, CurveFunctionSelectors, CurveInfo, - CreamFillData, DexSample, DODOFillData, ERC20BridgeSource, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 13c9089d7c..ee0a98ce23 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -159,13 +159,10 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), ); - let excludedSources: ERC20BridgeSource[] = []; - if (!sampleCreamOnChain) { - excludedSources = excludedSources.concat(ERC20BridgeSource.Cream); - } - if (!sampleBalancerOnChain) { - excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer); - } + const excludedSources = [ + ...(!sampleCreamOnChain ? [ERC20BridgeSource.Cream] : []), + ...(!sampleBalancerOnChain ? [ERC20BridgeSource.Balancer] : []), + ]; // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( @@ -303,13 +300,10 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), ); - let excludedSources: ERC20BridgeSource[] = []; - if (!sampleCreamOnChain) { - excludedSources = excludedSources.concat(ERC20BridgeSource.Cream); - } - if (!sampleBalancerOnChain) { - excludedSources = excludedSources.concat(ERC20BridgeSource.Balancer); - } + const excludedSources = [ + ...(!sampleCreamOnChain ? [ERC20BridgeSource.Cream] : []), + ...(!sampleBalancerOnChain ? [ERC20BridgeSource.Balancer] : []), + ]; // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index d12f0e1dea..e06b815718 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -22,7 +22,6 @@ import { BalancerFillData, BancorFillData, CollapsedFill, - CreamFillData, CurveFillData, DexSample, DODOFillData, @@ -179,7 +178,7 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath case ERC20BridgeSource.Balancer: return opts.contractAddresses.balancerBridge; case ERC20BridgeSource.Cream: - return opts.contractAddresses.balancerBridge; + return opts.contractAddresses.creamBridge; case ERC20BridgeSource.LiquidityProvider: return (fill.fillData as LiquidityProviderFillData).poolAddress; case ERC20BridgeSource.MultiBridge: @@ -245,7 +244,7 @@ export function createBridgeOrder( ); break; case ERC20BridgeSource.Cream: - const creamFillData = (fill as CollapsedFill).fillData!; // tslint:disable-line:no-non-null-assertion + const creamFillData = (fill as CollapsedFill).fillData!; // tslint:disable-line:no-non-null-assertion makerAssetData = assetDataUtils.encodeERC20BridgeAssetData( makerToken, bridgeAddress, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index d877ca9c93..b80b281720 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -19,7 +19,6 @@ import { BalancerFillData, BancorFillData, BatchedOperation, - CreamFillData, CurveFillData, CurveInfo, DexSample, @@ -413,9 +412,10 @@ export class SamplerOperations { makerToken: string, takerToken: string, takerFillAmounts: BigNumber[], + source: ERC20BridgeSource, ): SourceQuoteOperation { return new SamplerContractOperation({ - source: ERC20BridgeSource.Balancer, + source, fillData: { poolAddress }, contract: this._samplerContract, function: this._samplerContract.sampleSellsFromBalancer, @@ -428,9 +428,10 @@ export class SamplerOperations { makerToken: string, takerToken: string, makerFillAmounts: BigNumber[], + source: ERC20BridgeSource, ): SourceQuoteOperation { return new SamplerContractOperation({ - source: ERC20BridgeSource.Balancer, + source, fillData: { poolAddress }, contract: this._samplerContract, function: this._samplerContract.sampleBuysFromBalancer, @@ -470,41 +471,11 @@ export class SamplerOperations { ); } - public getCreamSellQuotes( - poolAddress: string, - makerToken: string, - takerToken: string, - takerFillAmounts: BigNumber[], - ): SourceQuoteOperation { - return new SamplerContractOperation({ - source: ERC20BridgeSource.Cream, - fillData: { poolAddress }, - contract: this._samplerContract, - function: this._samplerContract.sampleSellsFromBalancer, - params: [poolAddress, takerToken, makerToken, takerFillAmounts], - }); - } - - public getCreamBuyQuotes( - poolAddress: string, - makerToken: string, - takerToken: string, - makerFillAmounts: BigNumber[], - ): SourceQuoteOperation { - return new SamplerContractOperation({ - source: ERC20BridgeSource.Cream, - fillData: { poolAddress }, - contract: this._samplerContract, - function: this._samplerContract.sampleBuysFromBalancer, - params: [poolAddress, takerToken, makerToken, makerFillAmounts], - }); - } - public async getCreamSellQuotesOffChainAsync( makerToken: string, takerToken: string, takerFillAmounts: BigNumber[], - ): Promise>>> { + ): Promise>>> { const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); return pools.map(pool => takerFillAmounts.map(amount => ({ @@ -520,7 +491,7 @@ export class SamplerOperations { makerToken: string, takerToken: string, makerFillAmounts: BigNumber[], - ): Promise>>> { + ): Promise>>> { const pools = await this.creamPoolsCache.getPoolsForPairAsync(takerToken, makerToken); return pools.map(pool => makerFillAmounts.map(amount => ({ @@ -1103,13 +1074,13 @@ export class SamplerOperations { return this.balancerPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), + this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts, ERC20BridgeSource.Balancer), ); case ERC20BridgeSource.Cream: return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getCreamSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts), + this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts, ERC20BridgeSource.Cream), ); case ERC20BridgeSource.Shell: return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts); @@ -1200,13 +1171,13 @@ export class SamplerOperations { return this.balancerPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), + this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts, ERC20BridgeSource.Balancer), ); case ERC20BridgeSource.Cream: return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getCreamBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts), + this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts, ERC20BridgeSource.Cream), ); case ERC20BridgeSource.Shell: return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts); diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index 18c3d0b01d..43edff370a 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -105,10 +105,6 @@ export interface BalancerFillData extends FillData { poolAddress: string; } -export interface CreamFillData extends FillData { - poolAddress: string; -} - export interface UniswapV2FillData extends FillData { tokenAddressPath: string[]; } diff --git a/packages/contract-addresses/CHANGELOG.json b/packages/contract-addresses/CHANGELOG.json index 5db5010744..757a5e2b8e 100644 --- a/packages/contract-addresses/CHANGELOG.json +++ b/packages/contract-addresses/CHANGELOG.json @@ -57,6 +57,10 @@ { "note": "Deploy `DodoBridge` on Mainnet", "pr": 2701 + }, + { + "note": "Deploy `CreamBridge` on Mainnet", + "pr": 2715 } ] }, diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index ddb87a0fea..80aad5c1c8 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -45,6 +45,7 @@ "sushiswapBridge": "0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5", "shellBridge": "0x21fb3862eed7911e0f8219a077247b849846728d", "dodoBridge": "0xe9da66965a9344aab2167e6813c03f043cc7a6ca", + "creamBridge": "0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25", "transformers": { "wethTransformer": "0x68c0bb685099dc7cb5c5ce2b26185945b357383e", "payTakerTransformer": "0x49b9df2c58491764cf40cb052dd4243df63622c7", @@ -98,6 +99,7 @@ "sushiswapBridge": "0x0000000000000000000000000000000000000000", "shellBridge": "0x0000000000000000000000000000000000000000", "dodoBridge": "0x0000000000000000000000000000000000000000", + "creamBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437", "payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6", @@ -151,6 +153,7 @@ "sushiswapBridge": "0x0000000000000000000000000000000000000000", "shellBridge": "0x0000000000000000000000000000000000000000", "dodoBridge": "0x0000000000000000000000000000000000000000", + "creamBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437", "payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6", @@ -204,6 +207,7 @@ "sushiswapBridge": "0x0000000000000000000000000000000000000000", "shellBridge": "0x0000000000000000000000000000000000000000", "dodoBridge": "0x0000000000000000000000000000000000000000", + "creamBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x9ce35b5ee9e710535e3988e3f8731d9ca9dba17d", "payTakerTransformer": "0x5a53e7b02a83aa9f60ccf4e424f0442c255bc977", @@ -257,6 +261,7 @@ "sushiswapBridge": "0x0000000000000000000000000000000000000000", "shellBridge": "0x0000000000000000000000000000000000000000", "dodoBridge": "0x0000000000000000000000000000000000000000", + "creamBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5", "payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3", diff --git a/packages/contract-addresses/src/index.ts b/packages/contract-addresses/src/index.ts index 3c45f86ce3..a2f7c6be04 100644 --- a/packages/contract-addresses/src/index.ts +++ b/packages/contract-addresses/src/index.ts @@ -46,6 +46,7 @@ export interface ContractAddresses { sushiswapBridge: string; shellBridge: string; dodoBridge: string; + creamBridge: string; transformers: { wethTransformer: string; payTakerTransformer: string; From ac8b08d3cf25c2caa87f5e4f523356a57d303a11 Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Thu, 15 Oct 2020 23:35:23 -0700 Subject: [PATCH 09/10] Fix type error in migrations --- packages/migrations/src/migration.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index ae09eb2e6f..542eb7786f 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -406,6 +406,7 @@ export async function runMigrationsAsync( sushiswapBridge: NULL_ADDRESS, shellBridge: NULL_ADDRESS, dodoBridge: NULL_ADDRESS, + creamBridge: NULL_ADDRESS, exchangeProxy: exchangeProxy.address, exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress, exchangeProxyTransformerDeployer: txDefaults.from, From 088b331f1920e9d394e65b466a29f01c568a86ad Mon Sep 17 00:00:00 2001 From: Alex Kroeger Date: Fri, 16 Oct 2020 10:28:48 -0700 Subject: [PATCH 10/10] Prettier, cleared up naming --- .../src/utils/market_operation_utils/index.ts | 8 ++--- .../sampler_operations.ts | 32 ++++++++++++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 8f406f055f..c054959378 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -161,7 +161,7 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), ); - const excludedSources = [ + const offChainSources = [ ...(!sampleCreamOnChain ? [ERC20BridgeSource.Cream] : []), ...(!sampleBalancerOnChain ? [ERC20BridgeSource.Balancer] : []), ]; @@ -192,7 +192,7 @@ export class MarketOperationUtils { ), // Get sell quotes for taker -> maker. this._sampler.getSellQuotes( - quoteSourceFilters.exclude(excludedSources).sources, + quoteSourceFilters.exclude(offChainSources).sources, makerToken, takerToken, sampleAmounts, @@ -304,7 +304,7 @@ export class MarketOperationUtils { quoteSourceFilters.isAllowed(ERC20BridgeSource.Cream), ); - const excludedSources = [ + const offChainSources = [ ...(!sampleCreamOnChain ? [ERC20BridgeSource.Cream] : []), ...(!sampleBalancerOnChain ? [ERC20BridgeSource.Balancer] : []), ]; @@ -335,7 +335,7 @@ export class MarketOperationUtils { ), // Get buy quotes for taker -> maker. this._sampler.getBuyQuotes( - quoteSourceFilters.exclude(excludedSources).sources, + quoteSourceFilters.exclude(offChainSources).sources, makerToken, takerToken, sampleAmounts, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index d700eed974..5d5b0385a8 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -1075,13 +1075,25 @@ export class SamplerOperations { return this.balancerPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts, ERC20BridgeSource.Balancer), + this.getBalancerSellQuotes( + poolAddress, + makerToken, + takerToken, + takerFillAmounts, + ERC20BridgeSource.Balancer, + ), ); case ERC20BridgeSource.Cream: return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerSellQuotes(poolAddress, makerToken, takerToken, takerFillAmounts, ERC20BridgeSource.Cream), + this.getBalancerSellQuotes( + poolAddress, + makerToken, + takerToken, + takerFillAmounts, + ERC20BridgeSource.Cream, + ), ); case ERC20BridgeSource.Shell: return this.getShellSellQuotes(makerToken, takerToken, takerFillAmounts); @@ -1172,13 +1184,25 @@ export class SamplerOperations { return this.balancerPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts, ERC20BridgeSource.Balancer), + this.getBalancerBuyQuotes( + poolAddress, + makerToken, + takerToken, + makerFillAmounts, + ERC20BridgeSource.Balancer, + ), ); case ERC20BridgeSource.Cream: return this.creamPoolsCache .getCachedPoolAddressesForPair(takerToken, makerToken)! .map(poolAddress => - this.getBalancerBuyQuotes(poolAddress, makerToken, takerToken, makerFillAmounts, ERC20BridgeSource.Cream), + this.getBalancerBuyQuotes( + poolAddress, + makerToken, + takerToken, + makerFillAmounts, + ERC20BridgeSource.Cream, + ), ); case ERC20BridgeSource.Shell: return this.getShellBuyQuotes(makerToken, takerToken, makerFillAmounts);