MultiBridge support in AssetSwapper
This commit is contained in:
parent
0fbbabe208
commit
44262bf747
@ -21,6 +21,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add UniswapV2",
|
"note": "Add UniswapV2",
|
||||||
"pr": 2595
|
"pr": 2595
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Sample from MultiBridge",
|
||||||
|
"pr": 2593
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -35,6 +35,7 @@ import "./ICurve.sol";
|
|||||||
import "./ILiquidityProvider.sol";
|
import "./ILiquidityProvider.sol";
|
||||||
import "./ILiquidityProviderRegistry.sol";
|
import "./ILiquidityProviderRegistry.sol";
|
||||||
import "./IUniswapV2Router01.sol";
|
import "./IUniswapV2Router01.sol";
|
||||||
|
import "./IMultiBridge.sol";
|
||||||
|
|
||||||
|
|
||||||
contract ERC20BridgeSampler is
|
contract ERC20BridgeSampler is
|
||||||
@ -55,7 +56,7 @@ contract ERC20BridgeSampler is
|
|||||||
/// So a reasonable ceil is 150k per token. Biggest Curve has 4 tokens.
|
/// So a reasonable ceil is 150k per token. Biggest Curve has 4 tokens.
|
||||||
uint256 constant internal CURVE_CALL_GAS = 600e3; // 600k
|
uint256 constant internal CURVE_CALL_GAS = 600e3; // 600k
|
||||||
/// @dev Default gas limit for liquidity provider calls.
|
/// @dev Default gas limit for liquidity provider calls.
|
||||||
uint256 constant internal DEFAULT_CALL_GAS = 200e3; // 200k
|
uint256 constant internal DEFAULT_CALL_GAS = 400e3; // 400k
|
||||||
/// @dev The Kyber Uniswap Reserve address
|
/// @dev The Kyber Uniswap Reserve address
|
||||||
address constant internal KYBER_UNIWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F;
|
address constant internal KYBER_UNIWAP_RESERVE = 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F;
|
||||||
/// @dev The Kyber Eth2Dai Reserve address
|
/// @dev The Kyber Eth2Dai Reserve address
|
||||||
@ -593,6 +594,56 @@ contract ERC20BridgeSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from MultiBridge.
|
||||||
|
/// @param multibridge Address of the MultiBridge contract.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param intermediateToken The address of the intermediate token to
|
||||||
|
/// use in an indirect route.
|
||||||
|
/// @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 sampleSellsFromMultiBridge(
|
||||||
|
address multibridge,
|
||||||
|
address takerToken,
|
||||||
|
address intermediateToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256[] memory takerTokenAmounts
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts)
|
||||||
|
{
|
||||||
|
// Initialize array of maker token amounts.
|
||||||
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
|
|
||||||
|
// If no address provided, return all zeros.
|
||||||
|
if (multibridge == address(0)) {
|
||||||
|
return makerTokenAmounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
|
(bool didSucceed, bytes memory resultData) =
|
||||||
|
multibridge.staticcall.gas(DEFAULT_CALL_GAS)(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IMultiBridge(0).getSellQuote.selector,
|
||||||
|
takerToken,
|
||||||
|
intermediateToken,
|
||||||
|
makerToken,
|
||||||
|
takerTokenAmounts[i]
|
||||||
|
));
|
||||||
|
uint256 buyAmount = 0;
|
||||||
|
if (didSucceed) {
|
||||||
|
buyAmount = abi.decode(resultData, (uint256));
|
||||||
|
} else {
|
||||||
|
// Exit early if the amount is too high for the liquidity provider to serve
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
makerTokenAmounts[i] = buyAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
|
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
|
||||||
/// @param registryAddress Address of the liquidity provider registry contract.
|
/// @param registryAddress Address of the liquidity provider registry contract.
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
@ -206,6 +206,26 @@ interface IERC20BridgeSampler {
|
|||||||
view
|
view
|
||||||
returns (uint256[] memory makerTokenAmounts);
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from MultiBridge.
|
||||||
|
/// @param multibridge Address of the MultiBridge contract.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param intermediateToken The address of the intermediate token to
|
||||||
|
/// use in an indirect route.
|
||||||
|
/// @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 sampleSellsFromMultiBridge(
|
||||||
|
address multibridge,
|
||||||
|
address takerToken,
|
||||||
|
address intermediateToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256[] calldata takerTokenAmounts
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts);
|
||||||
|
|
||||||
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
|
/// @dev Sample buy quotes from an arbitrary on-chain liquidity provider.
|
||||||
/// @param registryAddress Address of the liquidity provider registry contract.
|
/// @param registryAddress Address of the liquidity provider registry contract.
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
interface IMultiBridge {
|
||||||
|
|
||||||
|
/// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`.
|
||||||
|
/// @param tokenAddress The address of the ERC20 token to transfer.
|
||||||
|
/// @param from Address to transfer asset from.
|
||||||
|
/// @param to Address to transfer asset to.
|
||||||
|
/// @param amount Amount of asset to transfer.
|
||||||
|
/// @param bridgeData Arbitrary asset data needed by the bridge contract.
|
||||||
|
/// @return success The magic bytes `0xdc1600f3` if successful.
|
||||||
|
function bridgeTransferFrom(
|
||||||
|
address tokenAddress,
|
||||||
|
address from,
|
||||||
|
address to,
|
||||||
|
uint256 amount,
|
||||||
|
bytes calldata bridgeData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4 success);
|
||||||
|
|
||||||
|
/// @dev Quotes the amount of `makerToken` that would be obtained by
|
||||||
|
/// selling `sellAmount` of `takerToken`.
|
||||||
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
|
/// @param intermediateToken The address of the intermediate token to
|
||||||
|
/// use in an indirect route.
|
||||||
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
|
/// @param sellAmount Amount of `takerToken` to sell.
|
||||||
|
/// @return makerTokenAmount Amount of `makerToken` that would be obtained.
|
||||||
|
function getSellQuote(
|
||||||
|
address takerToken,
|
||||||
|
address intermediateToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256 sellAmount
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (uint256 makerTokenAmount);
|
||||||
|
}
|
@ -38,7 +38,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
|
"publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
|
"abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -16,6 +16,7 @@ import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json';
|
|||||||
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
|
import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json';
|
||||||
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
|
import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json';
|
||||||
import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
|
import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json';
|
||||||
|
import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json';
|
||||||
import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
|
import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json';
|
||||||
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
|
import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json';
|
||||||
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
||||||
@ -31,6 +32,7 @@ export const artifacts = {
|
|||||||
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
|
IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact,
|
||||||
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
|
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
|
||||||
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
|
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
|
||||||
|
IMultiBridge: IMultiBridge as ContractArtifact,
|
||||||
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
|
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,
|
||||||
IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
|
IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact,
|
||||||
TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact,
|
TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact,
|
||||||
|
@ -14,6 +14,7 @@ export * from '../test/generated-wrappers/i_kyber_network';
|
|||||||
export * from '../test/generated-wrappers/i_kyber_network_proxy';
|
export * from '../test/generated-wrappers/i_kyber_network_proxy';
|
||||||
export * from '../test/generated-wrappers/i_liquidity_provider';
|
export * from '../test/generated-wrappers/i_liquidity_provider';
|
||||||
export * from '../test/generated-wrappers/i_liquidity_provider_registry';
|
export * from '../test/generated-wrappers/i_liquidity_provider_registry';
|
||||||
|
export * from '../test/generated-wrappers/i_multi_bridge';
|
||||||
export * from '../test/generated-wrappers/i_uniswap_exchange_quotes';
|
export * from '../test/generated-wrappers/i_uniswap_exchange_quotes';
|
||||||
export * from '../test/generated-wrappers/i_uniswap_v2_router01';
|
export * from '../test/generated-wrappers/i_uniswap_v2_router01';
|
||||||
export * from '../test/generated-wrappers/test_erc20_bridge_sampler';
|
export * from '../test/generated-wrappers/test_erc20_bridge_sampler';
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"test/generated-artifacts/IKyberNetworkProxy.json",
|
"test/generated-artifacts/IKyberNetworkProxy.json",
|
||||||
"test/generated-artifacts/ILiquidityProvider.json",
|
"test/generated-artifacts/ILiquidityProvider.json",
|
||||||
"test/generated-artifacts/ILiquidityProviderRegistry.json",
|
"test/generated-artifacts/ILiquidityProviderRegistry.json",
|
||||||
|
"test/generated-artifacts/IMultiBridge.json",
|
||||||
"test/generated-artifacts/IUniswapExchangeQuotes.json",
|
"test/generated-artifacts/IUniswapExchangeQuotes.json",
|
||||||
"test/generated-artifacts/IUniswapV2Router01.json",
|
"test/generated-artifacts/IUniswapV2Router01.json",
|
||||||
"test/generated-artifacts/TestERC20BridgeSampler.json"
|
"test/generated-artifacts/TestERC20BridgeSampler.json"
|
||||||
|
@ -81,6 +81,10 @@
|
|||||||
{
|
{
|
||||||
"note": "Add support for Uniswap V2",
|
"note": "Add support for Uniswap V2",
|
||||||
"pr": 2599
|
"pr": 2599
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add support for MultiBridge",
|
||||||
|
"pr": 2593
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -233,6 +233,7 @@ export interface SwapQuoterOpts extends OrderPrunerOpts {
|
|||||||
contractAddresses?: ContractAddresses;
|
contractAddresses?: ContractAddresses;
|
||||||
samplerGasLimit?: number;
|
samplerGasLimit?: number;
|
||||||
liquidityProviderRegistryAddress?: string;
|
liquidityProviderRegistryAddress?: string;
|
||||||
|
multiBridgeAddress?: string;
|
||||||
rfqt?: {
|
rfqt?: {
|
||||||
takerApiKeyWhitelist: string[];
|
takerApiKeyWhitelist: string[];
|
||||||
makerAssetOfferings: RfqtMakerAssetOfferings;
|
makerAssetOfferings: RfqtMakerAssetOfferings;
|
||||||
|
@ -158,11 +158,17 @@ function dexQuotesToPaths(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sourceToFillFlags(source: ERC20BridgeSource): number {
|
function sourceToFillFlags(source: ERC20BridgeSource): number {
|
||||||
if (source === ERC20BridgeSource.Kyber) {
|
switch (source) {
|
||||||
return FillFlags.Kyber;
|
case ERC20BridgeSource.Uniswap:
|
||||||
}
|
return FillFlags.ConflictsWithMultiBridge;
|
||||||
|
case ERC20BridgeSource.LiquidityProvider:
|
||||||
|
return FillFlags.ConflictsWithMultiBridge;
|
||||||
|
case ERC20BridgeSource.MultiBridge:
|
||||||
|
return FillFlags.MultiBridge;
|
||||||
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getPathSize(path: Fill[], targetInput: BigNumber = POSITIVE_INF): [BigNumber, BigNumber] {
|
export function getPathSize(path: Fill[], targetInput: BigNumber = POSITIVE_INF): [BigNumber, BigNumber] {
|
||||||
let input = ZERO_AMOUNT;
|
let input = ZERO_AMOUNT;
|
||||||
@ -217,8 +223,8 @@ export function isValidPath(path: Fill[], skipDuplicateCheck: boolean = false):
|
|||||||
}
|
}
|
||||||
flags |= path[i].flags;
|
flags |= path[i].flags;
|
||||||
}
|
}
|
||||||
const conflictFlags = FillFlags.Kyber | FillFlags.ConflictsWithKyber;
|
const multiBridgeConflict = FillFlags.MultiBridge | FillFlags.ConflictsWithMultiBridge;
|
||||||
return (flags & conflictFlags) !== conflictFlags;
|
return (flags & multiBridgeConflict) !== multiBridgeConflict;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clipPathToInput(path: Fill[], targetInput: BigNumber = POSITIVE_INF): Fill[] {
|
export function clipPathToInput(path: Fill[], targetInput: BigNumber = POSITIVE_INF): Fill[] {
|
||||||
|
@ -47,6 +47,7 @@ async function getRfqtIndicativeQuotesAsync(
|
|||||||
|
|
||||||
export class MarketOperationUtils {
|
export class MarketOperationUtils {
|
||||||
private readonly _wethAddress: string;
|
private readonly _wethAddress: string;
|
||||||
|
private readonly _multiBridge: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _sampler: DexOrderSampler,
|
private readonly _sampler: DexOrderSampler,
|
||||||
@ -55,6 +56,7 @@ export class MarketOperationUtils {
|
|||||||
private readonly _liquidityProviderRegistry: string = NULL_ADDRESS,
|
private readonly _liquidityProviderRegistry: string = NULL_ADDRESS,
|
||||||
) {
|
) {
|
||||||
this._wethAddress = contractAddresses.etherToken.toLowerCase();
|
this._wethAddress = contractAddresses.etherToken.toLowerCase();
|
||||||
|
this._multiBridge = contractAddresses.multiBridge.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,6 +77,11 @@ export class MarketOperationUtils {
|
|||||||
}
|
}
|
||||||
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
||||||
const [makerToken, takerToken] = getNativeOrderTokens(nativeOrders[0]);
|
const [makerToken, takerToken] = getNativeOrderTokens(nativeOrders[0]);
|
||||||
|
const optionalSources = (this._liquidityProviderRegistry !== NULL_ADDRESS
|
||||||
|
? [ERC20BridgeSource.LiquidityProvider]
|
||||||
|
: []
|
||||||
|
).concat(this._multiBridge !== NULL_ADDRESS ? [ERC20BridgeSource.MultiBridge] : []);
|
||||||
|
|
||||||
// Call the sampler contract.
|
// Call the sampler contract.
|
||||||
const samplerPromise = this._sampler.executeAsync(
|
const samplerPromise = this._sampler.executeAsync(
|
||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
@ -87,25 +94,23 @@ export class MarketOperationUtils {
|
|||||||
),
|
),
|
||||||
// Get ETH -> maker token price.
|
// Get ETH -> maker token price.
|
||||||
DexOrderSampler.ops.getMedianSellRate(
|
DexOrderSampler.ops.getMedianSellRate(
|
||||||
difference(FEE_QUOTE_SOURCES, _opts.excludedSources).concat(
|
difference(FEE_QUOTE_SOURCES.concat(optionalSources), _opts.excludedSources),
|
||||||
this._liquidityProviderSourceIfAvailable(_opts.excludedSources),
|
|
||||||
),
|
|
||||||
makerToken,
|
makerToken,
|
||||||
this._wethAddress,
|
this._wethAddress,
|
||||||
ONE_ETHER,
|
ONE_ETHER,
|
||||||
this._wethAddress,
|
this._wethAddress,
|
||||||
this._liquidityProviderRegistry,
|
this._liquidityProviderRegistry,
|
||||||
|
this._multiBridge,
|
||||||
),
|
),
|
||||||
// Get sell quotes for taker -> maker.
|
// Get sell quotes for taker -> maker.
|
||||||
DexOrderSampler.ops.getSellQuotes(
|
DexOrderSampler.ops.getSellQuotes(
|
||||||
difference(SELL_SOURCES, _opts.excludedSources).concat(
|
difference(SELL_SOURCES.concat(optionalSources), _opts.excludedSources),
|
||||||
this._liquidityProviderSourceIfAvailable(_opts.excludedSources),
|
|
||||||
),
|
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase),
|
||||||
this._wethAddress,
|
this._wethAddress,
|
||||||
this._liquidityProviderRegistry,
|
this._liquidityProviderRegistry,
|
||||||
|
this._multiBridge,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const rfqtPromise = getRfqtIndicativeQuotesAsync(
|
const rfqtPromise = getRfqtIndicativeQuotesAsync(
|
||||||
@ -125,6 +130,7 @@ export class MarketOperationUtils {
|
|||||||
dexQuotes,
|
dexQuotes,
|
||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
liquidityProviderAddress,
|
liquidityProviderAddress,
|
||||||
|
multiBridgeAddress: this._multiBridge,
|
||||||
inputToken: takerToken,
|
inputToken: takerToken,
|
||||||
outputToken: makerToken,
|
outputToken: makerToken,
|
||||||
side: MarketOperation.Sell,
|
side: MarketOperation.Sell,
|
||||||
@ -157,6 +163,10 @@ export class MarketOperationUtils {
|
|||||||
}
|
}
|
||||||
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
const _opts = { ...DEFAULT_GET_MARKET_ORDERS_OPTS, ...opts };
|
||||||
const [makerToken, takerToken] = getNativeOrderTokens(nativeOrders[0]);
|
const [makerToken, takerToken] = getNativeOrderTokens(nativeOrders[0]);
|
||||||
|
const optionalSources = (this._liquidityProviderRegistry !== NULL_ADDRESS
|
||||||
|
? [ERC20BridgeSource.LiquidityProvider]
|
||||||
|
: []
|
||||||
|
).concat(this._multiBridge !== NULL_ADDRESS ? [ERC20BridgeSource.MultiBridge] : []);
|
||||||
// Call the sampler contract.
|
// Call the sampler contract.
|
||||||
const samplerPromise = this._sampler.executeAsync(
|
const samplerPromise = this._sampler.executeAsync(
|
||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
@ -169,19 +179,21 @@ export class MarketOperationUtils {
|
|||||||
),
|
),
|
||||||
// Get ETH -> taker token price.
|
// Get ETH -> taker token price.
|
||||||
DexOrderSampler.ops.getMedianSellRate(
|
DexOrderSampler.ops.getMedianSellRate(
|
||||||
difference(FEE_QUOTE_SOURCES, _opts.excludedSources).concat(
|
difference(FEE_QUOTE_SOURCES.concat(optionalSources), _opts.excludedSources),
|
||||||
this._liquidityProviderSourceIfAvailable(_opts.excludedSources),
|
|
||||||
),
|
|
||||||
takerToken,
|
takerToken,
|
||||||
this._wethAddress,
|
this._wethAddress,
|
||||||
ONE_ETHER,
|
ONE_ETHER,
|
||||||
this._wethAddress,
|
this._wethAddress,
|
||||||
this._liquidityProviderRegistry,
|
this._liquidityProviderRegistry,
|
||||||
|
this._multiBridge,
|
||||||
),
|
),
|
||||||
// Get buy quotes for taker -> maker.
|
// Get buy quotes for taker -> maker.
|
||||||
DexOrderSampler.ops.getBuyQuotes(
|
DexOrderSampler.ops.getBuyQuotes(
|
||||||
difference(BUY_SOURCES, _opts.excludedSources).concat(
|
difference(
|
||||||
this._liquidityProviderSourceIfAvailable(_opts.excludedSources),
|
BUY_SOURCES.concat(
|
||||||
|
this._liquidityProviderRegistry !== NULL_ADDRESS ? [ERC20BridgeSource.LiquidityProvider] : [],
|
||||||
|
),
|
||||||
|
_opts.excludedSources,
|
||||||
),
|
),
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
@ -208,6 +220,7 @@ export class MarketOperationUtils {
|
|||||||
dexQuotes,
|
dexQuotes,
|
||||||
rfqtIndicativeQuotes,
|
rfqtIndicativeQuotes,
|
||||||
liquidityProviderAddress,
|
liquidityProviderAddress,
|
||||||
|
multiBridgeAddress: this._multiBridge,
|
||||||
inputToken: makerToken,
|
inputToken: makerToken,
|
||||||
outputToken: takerToken,
|
outputToken: takerToken,
|
||||||
side: MarketOperation.Buy,
|
side: MarketOperation.Buy,
|
||||||
@ -324,6 +337,7 @@ export class MarketOperationUtils {
|
|||||||
allowFallback?: boolean;
|
allowFallback?: boolean;
|
||||||
shouldBatchBridgeOrders?: boolean;
|
shouldBatchBridgeOrders?: boolean;
|
||||||
liquidityProviderAddress?: string;
|
liquidityProviderAddress?: string;
|
||||||
|
multiBridgeAddress?: string;
|
||||||
}): OptimizedMarketOrder[] {
|
}): OptimizedMarketOrder[] {
|
||||||
const { inputToken, outputToken, side, inputAmount } = opts;
|
const { inputToken, outputToken, side, inputAmount } = opts;
|
||||||
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
|
const maxFallbackSlippage = opts.maxFallbackSlippage || 0;
|
||||||
@ -385,16 +399,10 @@ export class MarketOperationUtils {
|
|||||||
contractAddresses: this.contractAddresses,
|
contractAddresses: this.contractAddresses,
|
||||||
bridgeSlippage: opts.bridgeSlippage || 0,
|
bridgeSlippage: opts.bridgeSlippage || 0,
|
||||||
liquidityProviderAddress: opts.liquidityProviderAddress,
|
liquidityProviderAddress: opts.liquidityProviderAddress,
|
||||||
|
multiBridgeAddress: opts.multiBridgeAddress,
|
||||||
shouldBatchBridgeOrders: !!opts.shouldBatchBridgeOrders,
|
shouldBatchBridgeOrders: !!opts.shouldBatchBridgeOrders,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _liquidityProviderSourceIfAvailable(excludedSources: ERC20BridgeSource[]): ERC20BridgeSource[] {
|
|
||||||
return this._liquidityProviderRegistry !== NULL_ADDRESS &&
|
|
||||||
!excludedSources.includes(ERC20BridgeSource.LiquidityProvider)
|
|
||||||
? [ERC20BridgeSource.LiquidityProvider]
|
|
||||||
: [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable: max-file-line-count
|
// tslint:disable: max-file-line-count
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
import { NULL_ADDRESS } from './constants';
|
||||||
|
|
||||||
|
// tslint:disable completed-docs
|
||||||
|
|
||||||
|
export const 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;
|
||||||
|
}
|
||||||
|
return intermediateToken;
|
||||||
|
}
|
@ -17,6 +17,7 @@ import {
|
|||||||
ZERO_AMOUNT,
|
ZERO_AMOUNT,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import { collapsePath } from './fills';
|
import { collapsePath } from './fills';
|
||||||
|
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
||||||
import {
|
import {
|
||||||
AggregationError,
|
AggregationError,
|
||||||
CollapsedFill,
|
CollapsedFill,
|
||||||
@ -141,6 +142,7 @@ export interface CreateOrderFromPathOpts {
|
|||||||
bridgeSlippage: number;
|
bridgeSlippage: number;
|
||||||
shouldBatchBridgeOrders: boolean;
|
shouldBatchBridgeOrders: boolean;
|
||||||
liquidityProviderAddress?: string;
|
liquidityProviderAddress?: string;
|
||||||
|
multiBridgeAddress?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert sell fills into orders.
|
// Convert sell fills into orders.
|
||||||
@ -195,6 +197,11 @@ function getBridgeAddressFromSource(source: ERC20BridgeSource, opts: CreateOrder
|
|||||||
throw new Error('Cannot create a LiquidityProvider order without a LiquidityProvider pool address.');
|
throw new Error('Cannot create a LiquidityProvider order without a LiquidityProvider pool address.');
|
||||||
}
|
}
|
||||||
return opts.liquidityProviderAddress;
|
return opts.liquidityProviderAddress;
|
||||||
|
case ERC20BridgeSource.MultiBridge:
|
||||||
|
if (opts.multiBridgeAddress === undefined) {
|
||||||
|
throw new Error('Cannot create a MultiBridge order without a MultiBridge address.');
|
||||||
|
}
|
||||||
|
return opts.multiBridgeAddress;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -242,6 +249,13 @@ function createBridgeOrder(fill: CollapsedFill, opts: CreateOrderFromPathOpts):
|
|||||||
createUniswapV2BridgeData([makerToken, opts.contractAddresses.etherToken, takerToken]),
|
createUniswapV2BridgeData([makerToken, opts.contractAddresses.etherToken, takerToken]),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case ERC20BridgeSource.MultiBridge:
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
|
makerToken,
|
||||||
|
bridgeAddress,
|
||||||
|
createMultiBridgeData(takerToken, makerToken),
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
makerToken,
|
makerToken,
|
||||||
@ -315,6 +329,15 @@ function createBridgeData(tokenAddress: string): string {
|
|||||||
return encoder.encode({ tokenAddress });
|
return encoder.encode({ tokenAddress });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createMultiBridgeData(takerToken: string, makerToken: string): string {
|
||||||
|
const intermediateToken = getMultiBridgeIntermediateToken(takerToken, makerToken);
|
||||||
|
const encoder = AbiEncoder.create([
|
||||||
|
{ name: 'takerToken', type: 'address' },
|
||||||
|
{ name: 'intermediateToken', type: 'address' },
|
||||||
|
]);
|
||||||
|
return encoder.encode({ takerToken, intermediateToken });
|
||||||
|
}
|
||||||
|
|
||||||
function createCurveBridgeData(
|
function createCurveBridgeData(
|
||||||
curveAddress: string,
|
curveAddress: string,
|
||||||
fromTokenIdx: number,
|
fromTokenIdx: number,
|
||||||
|
@ -2,6 +2,7 @@ import { BigNumber, ERC20BridgeSource, SignedOrder } from '../..';
|
|||||||
import { getCurveInfo, isCurveSource } from '../source_utils';
|
import { getCurveInfo, isCurveSource } from '../source_utils';
|
||||||
|
|
||||||
import { DEFAULT_FAKE_BUY_OPTS } from './constants';
|
import { DEFAULT_FAKE_BUY_OPTS } from './constants';
|
||||||
|
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
||||||
import { BatchedOperation, DexSample, FakeBuyOpts } from './types';
|
import { BatchedOperation, DexSample, FakeBuyOpts } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,7 +124,7 @@ export const samplerOperations = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getLiquidityProviderSellQuotes(
|
getLiquidityProviderSellQuotes(
|
||||||
liquidityProviderRegistryAddress: string,
|
registryAddress: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
takerFillAmounts: BigNumber[],
|
takerFillAmounts: BigNumber[],
|
||||||
@ -131,9 +132,31 @@ export const samplerOperations = {
|
|||||||
return {
|
return {
|
||||||
encodeCall: contract => {
|
encodeCall: contract => {
|
||||||
return contract
|
return contract
|
||||||
.sampleSellsFromLiquidityProviderRegistry(
|
.sampleSellsFromLiquidityProviderRegistry(registryAddress, takerToken, makerToken, takerFillAmounts)
|
||||||
liquidityProviderRegistryAddress,
|
.getABIEncodedTransactionData();
|
||||||
|
},
|
||||||
|
handleCallResultsAsync: async (contract, callResults) => {
|
||||||
|
return contract.getABIDecodedReturnData<BigNumber[]>(
|
||||||
|
'sampleSellsFromLiquidityProviderRegistry',
|
||||||
|
callResults,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getMultiBridgeSellQuotes(
|
||||||
|
multiBridgeAddress: string,
|
||||||
|
makerToken: string,
|
||||||
|
intermediateToken: string,
|
||||||
|
takerToken: string,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): BatchedOperation<BigNumber[]> {
|
||||||
|
return {
|
||||||
|
encodeCall: contract => {
|
||||||
|
return contract
|
||||||
|
.sampleSellsFromMultiBridge(
|
||||||
|
multiBridgeAddress,
|
||||||
takerToken,
|
takerToken,
|
||||||
|
intermediateToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerFillAmounts,
|
takerFillAmounts,
|
||||||
)
|
)
|
||||||
@ -148,7 +171,7 @@ export const samplerOperations = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getLiquidityProviderBuyQuotes(
|
getLiquidityProviderBuyQuotes(
|
||||||
liquidityProviderRegistryAddress: string,
|
registryAddress: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerFillAmounts: BigNumber[],
|
makerFillAmounts: BigNumber[],
|
||||||
@ -158,7 +181,7 @@ export const samplerOperations = {
|
|||||||
encodeCall: contract => {
|
encodeCall: contract => {
|
||||||
return contract
|
return contract
|
||||||
.sampleBuysFromLiquidityProviderRegistry(
|
.sampleBuysFromLiquidityProviderRegistry(
|
||||||
liquidityProviderRegistryAddress,
|
registryAddress,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
makerFillAmounts,
|
makerFillAmounts,
|
||||||
@ -256,7 +279,8 @@ export const samplerOperations = {
|
|||||||
takerToken: string,
|
takerToken: string,
|
||||||
takerFillAmount: BigNumber,
|
takerFillAmount: BigNumber,
|
||||||
wethAddress: string,
|
wethAddress: string,
|
||||||
liquidityProviderRegistryAddress?: string | undefined,
|
liquidityProviderRegistryAddress?: string,
|
||||||
|
multiBridgeAddress?: string,
|
||||||
): BatchedOperation<BigNumber> {
|
): BatchedOperation<BigNumber> {
|
||||||
if (makerToken.toLowerCase() === takerToken.toLowerCase()) {
|
if (makerToken.toLowerCase() === takerToken.toLowerCase()) {
|
||||||
return samplerOperations.constant(new BigNumber(1));
|
return samplerOperations.constant(new BigNumber(1));
|
||||||
@ -268,6 +292,7 @@ export const samplerOperations = {
|
|||||||
[takerFillAmount],
|
[takerFillAmount],
|
||||||
wethAddress,
|
wethAddress,
|
||||||
liquidityProviderRegistryAddress,
|
liquidityProviderRegistryAddress,
|
||||||
|
multiBridgeAddress,
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
encodeCall: contract => {
|
encodeCall: contract => {
|
||||||
@ -324,7 +349,8 @@ export const samplerOperations = {
|
|||||||
takerToken: string,
|
takerToken: string,
|
||||||
takerFillAmounts: BigNumber[],
|
takerFillAmounts: BigNumber[],
|
||||||
wethAddress: string,
|
wethAddress: string,
|
||||||
liquidityProviderRegistryAddress?: string | undefined,
|
liquidityProviderRegistryAddress?: string,
|
||||||
|
multiBridgeAddress?: string,
|
||||||
): BatchedOperation<DexSample[][]> {
|
): BatchedOperation<DexSample[][]> {
|
||||||
const subOps = sources
|
const subOps = sources
|
||||||
.map(source => {
|
.map(source => {
|
||||||
@ -367,6 +393,18 @@ export const samplerOperations = {
|
|||||||
takerToken,
|
takerToken,
|
||||||
takerFillAmounts,
|
takerFillAmounts,
|
||||||
);
|
);
|
||||||
|
} else if (source === ERC20BridgeSource.MultiBridge) {
|
||||||
|
if (multiBridgeAddress === undefined) {
|
||||||
|
throw new Error('Cannot sample liquidity from MultiBridge if an address is not provided.');
|
||||||
|
}
|
||||||
|
const intermediateToken = getMultiBridgeIntermediateToken(takerToken, makerToken);
|
||||||
|
batchedOperation = samplerOperations.getMultiBridgeSellQuotes(
|
||||||
|
multiBridgeAddress,
|
||||||
|
makerToken,
|
||||||
|
intermediateToken,
|
||||||
|
takerToken,
|
||||||
|
takerFillAmounts,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unsupported sell sample source: ${source}`);
|
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||||
}
|
}
|
||||||
@ -404,7 +442,7 @@ export const samplerOperations = {
|
|||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerFillAmounts: BigNumber[],
|
makerFillAmounts: BigNumber[],
|
||||||
wethAddress: string,
|
wethAddress: string,
|
||||||
liquidityProviderRegistryAddress?: string | undefined,
|
liquidityProviderRegistryAddress?: string,
|
||||||
fakeBuyOpts: FakeBuyOpts = DEFAULT_FAKE_BUY_OPTS,
|
fakeBuyOpts: FakeBuyOpts = DEFAULT_FAKE_BUY_OPTS,
|
||||||
): BatchedOperation<DexSample[][]> {
|
): BatchedOperation<DexSample[][]> {
|
||||||
const subOps = sources
|
const subOps = sources
|
||||||
|
@ -38,6 +38,7 @@ export enum ERC20BridgeSource {
|
|||||||
CurveUsdcDaiUsdtBusd = 'Curve_USDC_DAI_USDT_BUSD',
|
CurveUsdcDaiUsdtBusd = 'Curve_USDC_DAI_USDT_BUSD',
|
||||||
CurveUsdcDaiUsdtSusd = 'Curve_USDC_DAI_USDT_SUSD',
|
CurveUsdcDaiUsdtSusd = 'Curve_USDC_DAI_USDT_SUSD',
|
||||||
LiquidityProvider = 'LiquidityProvider',
|
LiquidityProvider = 'LiquidityProvider',
|
||||||
|
MultiBridge = 'MultiBridge',
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal `fillData` field for `Fill` objects.
|
// Internal `fillData` field for `Fill` objects.
|
||||||
@ -67,6 +68,8 @@ export interface DexSample {
|
|||||||
export enum FillFlags {
|
export enum FillFlags {
|
||||||
ConflictsWithKyber = 0x1,
|
ConflictsWithKyber = 0x1,
|
||||||
Kyber = 0x2,
|
Kyber = 0x2,
|
||||||
|
ConflictsWithMultiBridge = 0x4,
|
||||||
|
MultiBridge = 0x8,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,6 +212,48 @@ describe('DexSampler tests', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('getMultiBridgeSellQuotes()', async () => {
|
||||||
|
const expectedTakerToken = randomAddress();
|
||||||
|
const expectedMakerToken = randomAddress();
|
||||||
|
const multiBridge = randomAddress();
|
||||||
|
|
||||||
|
const sampler = new MockSamplerContract({
|
||||||
|
sampleSellsFromMultiBridge: (
|
||||||
|
multiBridgeAddress,
|
||||||
|
takerToken,
|
||||||
|
_intermediateToken,
|
||||||
|
makerToken,
|
||||||
|
_fillAmounts,
|
||||||
|
) => {
|
||||||
|
expect(multiBridgeAddress).to.eq(multiBridge);
|
||||||
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
|
return [toBaseUnitAmount(1001)];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const dexOrderSampler = new DexOrderSampler(sampler);
|
||||||
|
const [result] = await dexOrderSampler.executeAsync(
|
||||||
|
DexOrderSampler.ops.getSellQuotes(
|
||||||
|
[ERC20BridgeSource.MultiBridge],
|
||||||
|
expectedMakerToken,
|
||||||
|
expectedTakerToken,
|
||||||
|
[toBaseUnitAmount(1000)],
|
||||||
|
randomAddress(),
|
||||||
|
randomAddress(),
|
||||||
|
multiBridge,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(result).to.deep.equal([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
source: 'MultiBridge',
|
||||||
|
output: toBaseUnitAmount(1001),
|
||||||
|
input: toBaseUnitAmount(1000),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it('getEth2DaiSellQuotes()', async () => {
|
it('getEth2DaiSellQuotes()', async () => {
|
||||||
const expectedTakerToken = randomAddress();
|
const expectedTakerToken = randomAddress();
|
||||||
const expectedMakerToken = randomAddress();
|
const expectedMakerToken = randomAddress();
|
||||||
|
@ -30,7 +30,7 @@ import { DexSample, ERC20BridgeSource, NativeFillData } from '../src/utils/marke
|
|||||||
// tslint:disable: custom-no-magic-numbers
|
// tslint:disable: custom-no-magic-numbers
|
||||||
describe('MarketOperationUtils tests', () => {
|
describe('MarketOperationUtils tests', () => {
|
||||||
const CHAIN_ID = 1;
|
const CHAIN_ID = 1;
|
||||||
const contractAddresses = getContractAddressesForChainOrThrow(CHAIN_ID);
|
const contractAddresses = { ...getContractAddressesForChainOrThrow(CHAIN_ID), multiBridge: NULL_ADDRESS };
|
||||||
const ETH2DAI_BRIDGE_ADDRESS = contractAddresses.eth2DaiBridge;
|
const ETH2DAI_BRIDGE_ADDRESS = contractAddresses.eth2DaiBridge;
|
||||||
const KYBER_BRIDGE_ADDRESS = contractAddresses.kyberBridge;
|
const KYBER_BRIDGE_ADDRESS = contractAddresses.kyberBridge;
|
||||||
const UNISWAP_BRIDGE_ADDRESS = contractAddresses.uniswapBridge;
|
const UNISWAP_BRIDGE_ADDRESS = contractAddresses.uniswapBridge;
|
||||||
@ -259,7 +259,9 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
const fn = (registryAddress: string, takerToken: string, makerToken: string): string => {
|
const fn = (registryAddress: string, takerToken: string, makerToken: string): string => {
|
||||||
callArgs.makerToken = makerToken;
|
callArgs.makerToken = makerToken;
|
||||||
callArgs.takerToken = takerToken;
|
callArgs.takerToken = takerToken;
|
||||||
|
if (registryAddress !== constants.NULL_ADDRESS) {
|
||||||
callArgs.registryAddress = registryAddress;
|
callArgs.registryAddress = registryAddress;
|
||||||
|
}
|
||||||
return liquidityProviderAddress;
|
return liquidityProviderAddress;
|
||||||
};
|
};
|
||||||
return [callArgs, fn];
|
return [callArgs, fn];
|
||||||
@ -294,6 +296,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.CurveUsdcDaiUsdtBusd]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.CurveUsdcDaiUsdtBusd]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.CurveUsdcDaiUsdtSusd]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.CurveUsdcDaiUsdtSusd]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.LiquidityProvider]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.LiquidityProvider]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.MultiBridge]: _.times(NUM_SAMPLES, () => 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_OPS = {
|
const DEFAULT_OPS = {
|
||||||
|
@ -29,6 +29,13 @@ export type SampleSellsLPHandler = (
|
|||||||
takerTokenAmounts: BigNumber[],
|
takerTokenAmounts: BigNumber[],
|
||||||
) => SampleResults;
|
) => SampleResults;
|
||||||
export type SampleSellsMultihopHandler = (path: string[], takerTokenAmounts: BigNumber[]) => SampleResults;
|
export type SampleSellsMultihopHandler = (path: string[], takerTokenAmounts: BigNumber[]) => SampleResults;
|
||||||
|
export type SampleSellsMBHandler = (
|
||||||
|
multiBridgeAddress: string,
|
||||||
|
takerToken: string,
|
||||||
|
intermediateToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
takerTokenAmounts: BigNumber[],
|
||||||
|
) => SampleResults;
|
||||||
|
|
||||||
const DUMMY_PROVIDER = {
|
const DUMMY_PROVIDER = {
|
||||||
sendAsync: (...args: any[]): any => {
|
sendAsync: (...args: any[]): any => {
|
||||||
@ -41,6 +48,7 @@ interface Handlers {
|
|||||||
getOrderFillableTakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
getOrderFillableTakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
||||||
sampleSellsFromKyberNetwork: SampleSellsHandler;
|
sampleSellsFromKyberNetwork: SampleSellsHandler;
|
||||||
sampleSellsFromLiquidityProviderRegistry: SampleSellsLPHandler;
|
sampleSellsFromLiquidityProviderRegistry: SampleSellsLPHandler;
|
||||||
|
sampleSellsFromMultiBridge: SampleSellsMBHandler;
|
||||||
sampleSellsFromEth2Dai: SampleSellsHandler;
|
sampleSellsFromEth2Dai: SampleSellsHandler;
|
||||||
sampleSellsFromUniswap: SampleSellsHandler;
|
sampleSellsFromUniswap: SampleSellsHandler;
|
||||||
sampleSellsFromUniswapV2: SampleSellsMultihopHandler;
|
sampleSellsFromUniswapV2: SampleSellsMultihopHandler;
|
||||||
@ -159,6 +167,24 @@ export class MockSamplerContract extends IERC20BridgeSamplerContract {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sampleSellsFromMultiBridge(
|
||||||
|
multiBridgeAddress: string,
|
||||||
|
takerToken: string,
|
||||||
|
intermediateToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
takerAssetAmounts: BigNumber[],
|
||||||
|
): ContractFunctionObj<GetOrderFillableAssetAmountResult> {
|
||||||
|
return this._wrapCall(
|
||||||
|
super.sampleSellsFromMultiBridge,
|
||||||
|
this._handlers.sampleSellsFromMultiBridge,
|
||||||
|
multiBridgeAddress,
|
||||||
|
takerToken,
|
||||||
|
intermediateToken,
|
||||||
|
makerToken,
|
||||||
|
takerAssetAmounts,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public sampleBuysFromEth2Dai(
|
public sampleBuysFromEth2Dai(
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
|
@ -31,7 +31,8 @@
|
|||||||
"chainlinkStopLimit": "0xeb27220f95f364e1d9531992c48613f231839f53",
|
"chainlinkStopLimit": "0xeb27220f95f364e1d9531992c48613f231839f53",
|
||||||
"curveBridge": "0x6dc7950423ada9f56fb2c93a23edb787f1e29088",
|
"curveBridge": "0x6dc7950423ada9f56fb2c93a23edb787f1e29088",
|
||||||
"maximumGasPrice": "0xe2bfd35306495d11e3c9db0d8de390cda24563cf",
|
"maximumGasPrice": "0xe2bfd35306495d11e3c9db0d8de390cda24563cf",
|
||||||
"dexForwarderBridge": "0x5591360f8c7640fea5771c9682d6b5ecb776e1f8"
|
"dexForwarderBridge": "0x5591360f8c7640fea5771c9682d6b5ecb776e1f8",
|
||||||
|
"multiBridge": "0xc03117a8c9bde203f70aa911cb64a7a0df5ba1e1"
|
||||||
},
|
},
|
||||||
"3": {
|
"3": {
|
||||||
"erc20Proxy": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
"erc20Proxy": "0xb1408f4c245a23c31b98d2c626777d4c0d766caa",
|
||||||
@ -65,7 +66,8 @@
|
|||||||
"chainlinkStopLimit": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
|
"chainlinkStopLimit": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
|
||||||
"curveBridge": "0x0000000000000000000000000000000000000000",
|
"curveBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"maximumGasPrice": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
"maximumGasPrice": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
||||||
"dexForwarderBridge": "0x3be8e59038d8c4e8d8776ca40ef2f024bad95ad1"
|
"dexForwarderBridge": "0x3be8e59038d8c4e8d8776ca40ef2f024bad95ad1",
|
||||||
|
"multiBridge": "0x0000000000000000000000000000000000000000"
|
||||||
},
|
},
|
||||||
"4": {
|
"4": {
|
||||||
"exchangeV2": "0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
"exchangeV2": "0xbff9493f92a3df4b0429b6d00743b3cfb4c85831",
|
||||||
@ -99,7 +101,8 @@
|
|||||||
"chainlinkStopLimit": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
"chainlinkStopLimit": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
||||||
"curveBridge": "0x0000000000000000000000000000000000000000",
|
"curveBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"maximumGasPrice": "0x47697b44bd89051e93b4d5857ba8e024800a74ac",
|
"maximumGasPrice": "0x47697b44bd89051e93b4d5857ba8e024800a74ac",
|
||||||
"dexForwarderBridge": "0x0000000000000000000000000000000000000000"
|
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"multiBridge": "0x0000000000000000000000000000000000000000"
|
||||||
},
|
},
|
||||||
"42": {
|
"42": {
|
||||||
"erc20Proxy": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e",
|
"erc20Proxy": "0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e",
|
||||||
@ -133,7 +136,8 @@
|
|||||||
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
|
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
|
||||||
"curveBridge": "0x90c62c91a9f655f4f739e6cee85c84f9ccf47323",
|
"curveBridge": "0x90c62c91a9f655f4f739e6cee85c84f9ccf47323",
|
||||||
"maximumGasPrice": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
|
"maximumGasPrice": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
|
||||||
"dexForwarderBridge": "0x6cce442a48ab07635462a40594054f34f44195ff"
|
"dexForwarderBridge": "0x6cce442a48ab07635462a40594054f34f44195ff",
|
||||||
|
"multiBridge": "0x0000000000000000000000000000000000000000"
|
||||||
},
|
},
|
||||||
"1337": {
|
"1337": {
|
||||||
"erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
"erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
||||||
@ -167,6 +171,7 @@
|
|||||||
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
|
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
|
||||||
"curveBridge": "0x0000000000000000000000000000000000000000",
|
"curveBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"maximumGasPrice": "0x0000000000000000000000000000000000000000",
|
"maximumGasPrice": "0x0000000000000000000000000000000000000000",
|
||||||
"dexForwarderBridge": "0x0000000000000000000000000000000000000000"
|
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"multiBridge": "0x0000000000000000000000000000000000000000"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ export interface ContractAddresses {
|
|||||||
chainlinkStopLimit: string;
|
chainlinkStopLimit: string;
|
||||||
maximumGasPrice: string;
|
maximumGasPrice: string;
|
||||||
dexForwarderBridge: string;
|
dexForwarderBridge: string;
|
||||||
|
multiBridge: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ChainId {
|
export enum ChainId {
|
||||||
|
@ -323,6 +323,7 @@ export async function runMigrationsAsync(
|
|||||||
chainlinkStopLimit: constants.NULL_ADDRESS,
|
chainlinkStopLimit: constants.NULL_ADDRESS,
|
||||||
maximumGasPrice: constants.NULL_ADDRESS,
|
maximumGasPrice: constants.NULL_ADDRESS,
|
||||||
dexForwarderBridge: constants.NULL_ADDRESS,
|
dexForwarderBridge: constants.NULL_ADDRESS,
|
||||||
|
multiBridge: constants.NULL_ADDRESS,
|
||||||
};
|
};
|
||||||
return contractAddresses;
|
return contractAddresses;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user