fix: KyberDmm (#236)

* fix: KyberDmm

* fix: pass buyToken to kyberDmm and require that path ends with buyToken

* Pass BigNumber down to FastABI

* Address Feedback

Co-authored-by: Kim Persson <kimpersson88@gmail.com>
This commit is contained in:
Jacob Evans 2021-05-18 08:12:28 +10:00 committed by GitHub
parent 234ddb495d
commit 966d54c935
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 374 additions and 18 deletions

View File

@ -31,6 +31,7 @@ import "./mixins/MixinCryptoCom.sol";
import "./mixins/MixinDodo.sol"; import "./mixins/MixinDodo.sol";
import "./mixins/MixinDodoV2.sol"; import "./mixins/MixinDodoV2.sol";
import "./mixins/MixinKyber.sol"; import "./mixins/MixinKyber.sol";
import "./mixins/MixinKyberDmm.sol";
import "./mixins/MixinMakerPSM.sol"; import "./mixins/MixinMakerPSM.sol";
import "./mixins/MixinMooniswap.sol"; import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol"; import "./mixins/MixinMStable.sol";
@ -53,6 +54,7 @@ contract BridgeAdapter is
MixinDodo, MixinDodo,
MixinDodoV2, MixinDodoV2,
MixinKyber, MixinKyber,
MixinKyberDmm,
MixinMakerPSM, MixinMakerPSM,
MixinMooniswap, MixinMooniswap,
MixinMStable, MixinMStable,
@ -217,6 +219,12 @@ contract BridgeAdapter is
sellAmount, sellAmount,
order.bridgeData order.bridgeData
); );
} else if (protocolId == BridgeProtocols.KYBERDMM) {
boughtAmount = _tradeKyberDmm(
buyToken,
sellAmount,
order.bridgeData
);
} else { } else {
boughtAmount = _tradeZeroExBridge( boughtAmount = _tradeZeroExBridge(
sellToken, sellToken,

View File

@ -46,4 +46,5 @@ library BridgeProtocols {
uint128 internal constant MAKERPSM = 16; uint128 internal constant MAKERPSM = 16;
uint128 internal constant BALANCERV2 = 17; uint128 internal constant BALANCERV2 = 17;
uint128 internal constant UNISWAPV3 = 18; uint128 internal constant UNISWAPV3 = 18;
uint128 internal constant KYBERDMM = 19;
} }

View File

@ -0,0 +1,94 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright 2021 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.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../IBridgeAdapter.sol";
/*
KyberDmm Router
*/
interface IKyberDmmRouter {
/// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path.
/// The first element of path is the input token, the last is the output token, and any intermediate elements represent
/// intermediate pairs to trade through (if, for example, a direct pair does not exist).
/// @param amountIn The amount of input tokens to send.
/// @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.
/// @param pools An array of pool addresses. pools.length must be >= 1.
/// @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity.
/// @param to Recipient of the output tokens.
/// @param deadline Unix timestamp after which the transaction will revert.
/// @return amounts The input token amount and all subsequent output token amounts.
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata pools,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
contract MixinKyberDmm {
using LibERC20TokenV06 for IERC20TokenV06;
function _tradeKyberDmm(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
address router;
address[] memory pools;
address[] memory path;
(router, pools, path) = abi.decode(bridgeData, (address, address[], address[]));
require(pools.length >= 1, "MixinKyberDmm/POOLS_LENGTH_MUST_BE_AT_LEAST_ONE");
require(path.length == pools.length + 1, "MixinKyberDmm/ARRAY_LENGTH_MISMATCH");
require(
path[path.length - 1] == address(buyToken),
"MixinKyberDmm/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
// Grant the KyberDmm router an allowance to sell the first token.
IERC20TokenV06(path[0]).approveIfBelow(address(router), sellAmount);
uint[] memory amounts = IKyberDmmRouter(router).swapExactTokensForTokens(
// Sell all tokens we hold.
sellAmount,
// Minimum buy amount.
1,
pools,
// Convert to `buyToken` along this path.
path,
// Recipient is `this`.
address(this),
// Expires after this block.
block.timestamp
);
return amounts[amounts.length-1];
}
}

View File

@ -69,7 +69,7 @@ contract MixinUniswapV2 {
assembly { path := _path } assembly { path := _path }
} }
require(path.length >= 2, "MixinUniswapV3/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); require(path.length >= 2, "MixinUniswapV2/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require( require(
path[path.length - 1] == buyToken, path[path.length - 1] == buyToken,
"MixinUniswapV2/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN" "MixinUniswapV2/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"

View File

@ -43,7 +43,7 @@
"config": { "config": {
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature", "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
"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/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json" "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -84,6 +84,7 @@ import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json'; import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json';
import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json'; import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json';
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json'; import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
import * as MixinKyberDmm from '../test/generated-artifacts/MixinKyberDmm.json';
import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json'; import * as MixinMakerPSM from '../test/generated-artifacts/MixinMakerPSM.json';
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json'; import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json'; import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
@ -245,6 +246,7 @@ export const artifacts = {
MixinDodo: MixinDodo as ContractArtifact, MixinDodo: MixinDodo as ContractArtifact,
MixinDodoV2: MixinDodoV2 as ContractArtifact, MixinDodoV2: MixinDodoV2 as ContractArtifact,
MixinKyber: MixinKyber as ContractArtifact, MixinKyber: MixinKyber as ContractArtifact,
MixinKyberDmm: MixinKyberDmm as ContractArtifact,
MixinMStable: MixinMStable as ContractArtifact, MixinMStable: MixinMStable as ContractArtifact,
MixinMakerPSM: MixinMakerPSM as ContractArtifact, MixinMakerPSM: MixinMakerPSM as ContractArtifact,
MixinMooniswap: MixinMooniswap as ContractArtifact, MixinMooniswap: MixinMooniswap as ContractArtifact,

View File

@ -82,6 +82,7 @@ export * from '../test/generated-wrappers/mixin_curve';
export * from '../test/generated-wrappers/mixin_dodo'; export * from '../test/generated-wrappers/mixin_dodo';
export * from '../test/generated-wrappers/mixin_dodo_v2'; export * from '../test/generated-wrappers/mixin_dodo_v2';
export * from '../test/generated-wrappers/mixin_kyber'; export * from '../test/generated-wrappers/mixin_kyber';
export * from '../test/generated-wrappers/mixin_kyber_dmm';
export * from '../test/generated-wrappers/mixin_m_stable'; export * from '../test/generated-wrappers/mixin_m_stable';
export * from '../test/generated-wrappers/mixin_maker_p_s_m'; export * from '../test/generated-wrappers/mixin_maker_p_s_m';
export * from '../test/generated-wrappers/mixin_mooniswap'; export * from '../test/generated-wrappers/mixin_mooniswap';

View File

@ -113,6 +113,7 @@
"test/generated-artifacts/MixinDodo.json", "test/generated-artifacts/MixinDodo.json",
"test/generated-artifacts/MixinDodoV2.json", "test/generated-artifacts/MixinDodoV2.json",
"test/generated-artifacts/MixinKyber.json", "test/generated-artifacts/MixinKyber.json",
"test/generated-artifacts/MixinKyberDmm.json",
"test/generated-artifacts/MixinMStable.json", "test/generated-artifacts/MixinMStable.json",
"test/generated-artifacts/MixinMakerPSM.json", "test/generated-artifacts/MixinMakerPSM.json",
"test/generated-artifacts/MixinMooniswap.json", "test/generated-artifacts/MixinMooniswap.json",

View File

@ -1,4 +1,13 @@
[ [
{
"version": "6.15.0",
"changes": [
{
"note": "Fix KyberDmm",
"pr": 236
}
]
},
{ {
"version": "6.14.0", "version": "6.14.0",
"changes": [ "changes": [

View File

@ -28,6 +28,7 @@ import "./DODOSampler.sol";
import "./DODOV2Sampler.sol"; import "./DODOV2Sampler.sol";
import "./Eth2DaiSampler.sol"; import "./Eth2DaiSampler.sol";
import "./KyberSampler.sol"; import "./KyberSampler.sol";
import "./KyberDmmSampler.sol";
import "./LiquidityProviderSampler.sol"; import "./LiquidityProviderSampler.sol";
import "./MakerPSMSampler.sol"; import "./MakerPSMSampler.sol";
import "./MultiBridgeSampler.sol"; import "./MultiBridgeSampler.sol";
@ -52,6 +53,7 @@ contract ERC20BridgeSampler is
DODOV2Sampler, DODOV2Sampler,
Eth2DaiSampler, Eth2DaiSampler,
KyberSampler, KyberSampler,
KyberDmmSampler,
LiquidityProviderSampler, LiquidityProviderSampler,
MakerPSMSampler, MakerPSMSampler,
MStableSampler, MStableSampler,

View File

@ -0,0 +1,159 @@
// SPDX-License-Identifier: Apache-2.0
/*
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.6;
pragma experimental ABIEncoderV2;
interface IKyberDmmFactory {
function getPoolAtIndex(address token0, address token1, uint256 index)
external
view
returns (address);
}
interface IKyberDmmRouter {
function factory() external view returns (address);
function getAmountsOut(uint256 amountIn, address[] calldata pools, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata pools, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}
contract KyberDmmSampler
{
/// @dev Gas limit for KyberDmm calls.
uint256 constant private KYBER_DMM_CALL_GAS = 150e3; // 150k
/// @dev Sample sell quotes from KyberDmm.
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return pools The pool addresses involved in the multi path trade
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromKyberDmm(
address router,
address[] memory path,
uint256[] memory takerTokenAmounts
)
public
view
returns (address[] memory pools, uint256[] memory makerTokenAmounts)
{
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
pools = _getKyberDmmPools(router, path);
if (pools.length == 0) {
return (pools, makerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
try
IKyberDmmRouter(router).getAmountsOut
{gas: KYBER_DMM_CALL_GAS}
(takerTokenAmounts[i], pools, path)
returns (uint256[] memory amounts)
{
makerTokenAmounts[i] = amounts[path.length - 1];
// Break early if there are 0 amounts
if (makerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
/// @dev Sample buy quotes from KyberDmm.
/// @param router Router to look up tokens and amounts
/// @param path Token route. Should be takerToken -> makerToken.
/// @param makerTokenAmounts Maker token buy amount for each sample.
/// @return pools The pool addresses involved in the multi path trade
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromKyberDmm(
address router,
address[] memory path,
uint256[] memory makerTokenAmounts
)
public
view
returns (address[] memory pools, uint256[] memory takerTokenAmounts)
{
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
pools = _getKyberDmmPools(router, path);
if (pools.length == 0) {
return (pools, takerTokenAmounts);
}
for (uint256 i = 0; i < numSamples; i++) {
try
IKyberDmmRouter(router).getAmountsIn
{gas: KYBER_DMM_CALL_GAS}
(makerTokenAmounts[i], pools, path)
returns (uint256[] memory amounts)
{
takerTokenAmounts[i] = amounts[0];
// Break early if there are 0 amounts
if (takerTokenAmounts[i] == 0) {
break;
}
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
}
}
function _getKyberDmmPools(
address router,
address[] memory path
)
private
view
returns (address[] memory pools)
{
pools = new address[](path.length - 1);
IKyberDmmFactory factory = IKyberDmmFactory(IKyberDmmRouter(router).factory());
for (uint256 i = 0; i < pools.length; i++) {
// Currently only supporting the first pool found at the index
try
factory.getPoolAtIndex
{gas: KYBER_DMM_CALL_GAS}
(path[i], path[i + 1], 0)
returns (address pool)
{
pools[i] = pool;
} catch (bytes memory) {
return new address[](0);
}
}
}
}

View File

@ -39,7 +39,7 @@
"config": { "config": {
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker", "publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
"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/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json", "abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BalancerV2Sampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|ISmoothy|IUniswapExchangeQuotes|IUniswapV2Router01|KyberDmmSampler|KyberSampler|LiquidityProviderSampler|MStableSampler|MakerPSMSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SmoothySampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UniswapV3Sampler|UtilitySampler).json",
"postpublish": { "postpublish": {
"assets": [] "assets": []
} }

View File

@ -125,7 +125,7 @@ export class SwapQuoter {
{ block: BlockParamLiteral.Latest, overrides: defaultCodeOverrides }, { block: BlockParamLiteral.Latest, overrides: defaultCodeOverrides },
options.samplerOverrides, options.samplerOverrides,
); );
const fastAbi = new FastABI(ERC20BridgeSamplerContract.ABI() as MethodAbi[]); const fastAbi = new FastABI(ERC20BridgeSamplerContract.ABI() as MethodAbi[], { BigNumber });
const samplerContract = new ERC20BridgeSamplerContract( const samplerContract = new ERC20BridgeSamplerContract(
samplerAddress, samplerAddress,
this.provider, this.provider,

View File

@ -14,7 +14,6 @@ import {
JULSWAP_ROUTER_BY_CHAIN_ID, JULSWAP_ROUTER_BY_CHAIN_ID,
KYBER_BANNED_RESERVES, KYBER_BANNED_RESERVES,
KYBER_BRIDGED_LIQUIDITY_PREFIX, KYBER_BRIDGED_LIQUIDITY_PREFIX,
KYBER_DMM_ROUTER_BY_CHAIN_ID,
MAX_DODOV2_POOLS_QUERIED, MAX_DODOV2_POOLS_QUERIED,
MAX_KYBER_RESERVES_QUERIED, MAX_KYBER_RESERVES_QUERIED,
MSTABLE_POOLS_BY_CHAIN_ID, MSTABLE_POOLS_BY_CHAIN_ID,
@ -314,7 +313,6 @@ export function uniswapV2LikeRouterAddress(
| ERC20BridgeSource.PancakeSwap | ERC20BridgeSource.PancakeSwap
| ERC20BridgeSource.PancakeSwapV2 | ERC20BridgeSource.PancakeSwapV2
| ERC20BridgeSource.BakerySwap | ERC20BridgeSource.BakerySwap
| ERC20BridgeSource.KyberDmm
| ERC20BridgeSource.ApeSwap | ERC20BridgeSource.ApeSwap
| ERC20BridgeSource.CafeSwap | ERC20BridgeSource.CafeSwap
| ERC20BridgeSource.CheeseSwap | ERC20BridgeSource.CheeseSwap
@ -333,8 +331,6 @@ export function uniswapV2LikeRouterAddress(
return PANCAKESWAPV2_ROUTER_BY_CHAIN_ID[chainId]; return PANCAKESWAPV2_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.BakerySwap:
return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId]; return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.KyberDmm:
return KYBER_DMM_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.ApeSwap: case ERC20BridgeSource.ApeSwap:
return APESWAP_ROUTER_BY_CHAIN_ID[chainId]; return APESWAP_ROUTER_BY_CHAIN_ID[chainId];
case ERC20BridgeSource.CafeSwap: case ERC20BridgeSource.CafeSwap:

View File

@ -85,7 +85,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.CryptoCom, ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
ERC20BridgeSource.MakerPsm, ERC20BridgeSource.MakerPsm,
ERC20BridgeSource.KyberDmm, // ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.Smoothy, ERC20BridgeSource.Smoothy,
ERC20BridgeSource.Component, ERC20BridgeSource.Component,
ERC20BridgeSource.Saddle, ERC20BridgeSource.Saddle,
@ -158,7 +158,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
ERC20BridgeSource.CryptoCom, ERC20BridgeSource.CryptoCom,
ERC20BridgeSource.Linkswap, ERC20BridgeSource.Linkswap,
ERC20BridgeSource.MakerPsm, ERC20BridgeSource.MakerPsm,
ERC20BridgeSource.KyberDmm, // ERC20BridgeSource.KyberDmm,
ERC20BridgeSource.Smoothy, ERC20BridgeSource.Smoothy,
ERC20BridgeSource.Component, ERC20BridgeSource.Component,
ERC20BridgeSource.Saddle, ERC20BridgeSource.Saddle,
@ -941,7 +941,7 @@ export const OASIS_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
export const KYBER_DMM_ROUTER_BY_CHAIN_ID = valueByChainId<string>( export const KYBER_DMM_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
{ {
[ChainId.Mainnet]: '0x12807818B584a3Fa65D38B6C25B13983fE888D6E', [ChainId.Mainnet]: '0x1c87257f5e8609940bc751a07bb085bb7f8cdbe6',
}, },
NULL_ADDRESS, NULL_ADDRESS,
); );

View File

@ -16,6 +16,7 @@ import {
ERC20BridgeSource, ERC20BridgeSource,
FillData, FillData,
GenericRouterFillData, GenericRouterFillData,
KyberDmmFillData,
KyberFillData, KyberFillData,
LiquidityProviderFillData, LiquidityProviderFillData,
MakerPsmFillData, MakerPsmFillData,
@ -99,8 +100,6 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo'); return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo');
case ERC20BridgeSource.Kyber: case ERC20BridgeSource.Kyber:
return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber'); return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber');
case ERC20BridgeSource.KyberDmm:
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'KyberDmm');
case ERC20BridgeSource.LiquidityProvider: case ERC20BridgeSource.LiquidityProvider:
// "LiquidityProvider" is too long to encode (17 characters). // "LiquidityProvider" is too long to encode (17 characters).
return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP'); return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP');
@ -158,6 +157,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'JulSwap'); return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'JulSwap');
case ERC20BridgeSource.UniswapV3: case ERC20BridgeSource.UniswapV3:
return encodeBridgeSourceId(BridgeProtocol.UniswapV3, 'UniswapV3'); return encodeBridgeSourceId(BridgeProtocol.UniswapV3, 'UniswapV3');
case ERC20BridgeSource.KyberDmm:
return encodeBridgeSourceId(BridgeProtocol.KyberDmm, 'KyberDmm');
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -217,7 +218,6 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.ApeSwap: case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap: case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap: case ERC20BridgeSource.CheeseSwap:
@ -274,6 +274,14 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
const uniswapV3FillData = (order as OptimizedMarketBridgeOrder<FinalUniswapV3FillData>).fillData; const uniswapV3FillData = (order as OptimizedMarketBridgeOrder<FinalUniswapV3FillData>).fillData;
bridgeData = encoder.encode([uniswapV3FillData.router, uniswapV3FillData.uniswapPath]); bridgeData = encoder.encode([uniswapV3FillData.router, uniswapV3FillData.uniswapPath]);
break; break;
case ERC20BridgeSource.KyberDmm:
const kyberDmmFillData = (order as OptimizedMarketBridgeOrder<KyberDmmFillData>).fillData;
bridgeData = encoder.encode([
kyberDmmFillData.router,
kyberDmmFillData.poolsPath,
kyberDmmFillData.tokenAddressPath,
]);
break;
default: default:
throw new Error(AggregationError.NoBridgeForSource); throw new Error(AggregationError.NoBridgeForSource);
} }
@ -390,7 +398,6 @@ export const BRIDGE_ENCODERS: {
[ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder, [ERC20BridgeSource.SushiSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder, [ERC20BridgeSource.CryptoCom]: routerAddressPathEncoder,
[ERC20BridgeSource.Linkswap]: routerAddressPathEncoder, [ERC20BridgeSource.Linkswap]: routerAddressPathEncoder,
[ERC20BridgeSource.KyberDmm]: routerAddressPathEncoder,
// BSC // BSC
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder, [ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
[ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder, [ERC20BridgeSource.PancakeSwapV2]: routerAddressPathEncoder,
@ -415,6 +422,7 @@ export const BRIDGE_ENCODERS: {
{ name: 'router', type: 'address' }, { name: 'router', type: 'address' },
{ name: 'path', type: 'bytes' }, { name: 'path', type: 'bytes' },
]), ]),
[ERC20BridgeSource.KyberDmm]: AbiEncoder.create('(address,address[],address[])'),
}; };
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] { function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {

View File

@ -23,6 +23,7 @@ import {
DODO_CONFIG_BY_CHAIN_ID, DODO_CONFIG_BY_CHAIN_ID,
DODOV2_FACTORIES_BY_CHAIN_ID, DODOV2_FACTORIES_BY_CHAIN_ID,
KYBER_CONFIG_BY_CHAIN_ID, KYBER_CONFIG_BY_CHAIN_ID,
KYBER_DMM_ROUTER_BY_CHAIN_ID,
LINKSWAP_ROUTER_BY_CHAIN_ID, LINKSWAP_ROUTER_BY_CHAIN_ID,
LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID, LIQUIDITY_PROVIDER_REGISTRY_BY_CHAIN_ID,
MAINNET_TOKENS, MAINNET_TOKENS,
@ -56,6 +57,7 @@ import {
ERC20BridgeSource, ERC20BridgeSource,
GenericRouterFillData, GenericRouterFillData,
HopInfo, HopInfo,
KyberDmmFillData,
KyberFillData, KyberFillData,
KyberSamplerOpts, KyberSamplerOpts,
LiquidityProviderFillData, LiquidityProviderFillData,
@ -236,6 +238,52 @@ export class SamplerOperations {
}); });
} }
public getKyberDmmSellQuotes(
router: string,
tokenAddressPath: string[],
takerFillAmounts: BigNumber[],
): SourceQuoteOperation<KyberDmmFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.KyberDmm,
contract: this._samplerContract,
function: this._samplerContract.sampleSellsFromKyberDmm,
params: [router, tokenAddressPath, takerFillAmounts],
callback: (callResults: string, fillData: KyberDmmFillData): BigNumber[] => {
const [pools, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>(
'sampleSellsFromKyberDmm',
callResults,
);
fillData.poolsPath = pools;
fillData.router = router;
fillData.tokenAddressPath = tokenAddressPath;
return samples;
},
});
}
public getKyberDmmBuyQuotes(
router: string,
tokenAddressPath: string[],
makerFillAmounts: BigNumber[],
): SourceQuoteOperation<KyberDmmFillData> {
return new SamplerContractOperation({
source: ERC20BridgeSource.KyberDmm,
contract: this._samplerContract,
function: this._samplerContract.sampleBuysFromKyberDmm,
params: [router, tokenAddressPath, makerFillAmounts],
callback: (callResults: string, fillData: KyberDmmFillData): BigNumber[] => {
const [pools, samples] = this._samplerContract.getABIDecodedReturnData<[string[], BigNumber[]]>(
'sampleBuysFromKyberDmm',
callResults,
);
fillData.poolsPath = pools;
fillData.router = router;
fillData.tokenAddressPath = tokenAddressPath;
return samples;
},
});
}
public getUniswapSellQuotes( public getUniswapSellQuotes(
router: string, router: string,
makerToken: string, makerToken: string,
@ -1134,7 +1182,6 @@ export class SamplerOperations {
case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.ApeSwap: case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap: case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap: case ERC20BridgeSource.CheeseSwap:
@ -1147,6 +1194,16 @@ export class SamplerOperations {
[takerToken, makerToken], [takerToken, makerToken],
...intermediateTokens.map(t => [takerToken, t, makerToken]), ...intermediateTokens.map(t => [takerToken, t, makerToken]),
].map(path => this.getUniswapV2SellQuotes(uniLikeRouter, path, takerFillAmounts, source)); ].map(path => this.getUniswapV2SellQuotes(uniLikeRouter, path, takerFillAmounts, source));
case ERC20BridgeSource.KyberDmm:
const kyberDmmRouter = KYBER_DMM_ROUTER_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(kyberDmmRouter)) {
return [];
}
return this.getKyberDmmSellQuotes(
kyberDmmRouter,
[takerToken, makerToken],
takerFillAmounts,
);
case ERC20BridgeSource.Kyber: case ERC20BridgeSource.Kyber:
return getKyberOffsets().map(offset => return getKyberOffsets().map(offset =>
this.getKyberSellQuotes( this.getKyberSellQuotes(
@ -1381,7 +1438,6 @@ export class SamplerOperations {
case ERC20BridgeSource.PancakeSwap: case ERC20BridgeSource.PancakeSwap:
case ERC20BridgeSource.PancakeSwapV2: case ERC20BridgeSource.PancakeSwapV2:
case ERC20BridgeSource.BakerySwap: case ERC20BridgeSource.BakerySwap:
case ERC20BridgeSource.KyberDmm:
case ERC20BridgeSource.ApeSwap: case ERC20BridgeSource.ApeSwap:
case ERC20BridgeSource.CafeSwap: case ERC20BridgeSource.CafeSwap:
case ERC20BridgeSource.CheeseSwap: case ERC20BridgeSource.CheeseSwap:
@ -1394,6 +1450,16 @@ export class SamplerOperations {
[takerToken, makerToken], [takerToken, makerToken],
...intermediateTokens.map(t => [takerToken, t, makerToken]), ...intermediateTokens.map(t => [takerToken, t, makerToken]),
].map(path => this.getUniswapV2BuyQuotes(uniLikeRouter, path, makerFillAmounts, source)); ].map(path => this.getUniswapV2BuyQuotes(uniLikeRouter, path, makerFillAmounts, source));
case ERC20BridgeSource.KyberDmm:
const kyberDmmRouter = KYBER_DMM_ROUTER_BY_CHAIN_ID[this.chainId];
if (!isValidAddress(kyberDmmRouter)) {
return [];
}
return this.getKyberDmmBuyQuotes(
kyberDmmRouter,
[takerToken, makerToken],
makerFillAmounts,
);
case ERC20BridgeSource.Kyber: case ERC20BridgeSource.Kyber:
return getKyberOffsets().map(offset => return getKyberOffsets().map(offset =>
this.getKyberBuyQuotes( this.getKyberBuyQuotes(

View File

@ -224,6 +224,10 @@ export interface UniswapV3FillData extends FillData {
pathAmounts: Array<{ uniswapPath: string; inputAmount: BigNumber }>; pathAmounts: Array<{ uniswapPath: string; inputAmount: BigNumber }>;
} }
export interface KyberDmmFillData extends UniswapV2FillData {
poolsPath: string[];
}
/** /**
* Represents a node on a fill path. * Represents a node on a fill path.
*/ */

View File

@ -29,6 +29,7 @@ import * as IShell from '../test/generated-artifacts/IShell.json';
import * as ISmoothy from '../test/generated-artifacts/ISmoothy.json'; import * as ISmoothy from '../test/generated-artifacts/ISmoothy.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 KyberDmmSampler from '../test/generated-artifacts/KyberDmmSampler.json';
import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json'; import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json';
import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json'; import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json';
import * as MakerPSMSampler from '../test/generated-artifacts/MakerPSMSampler.json'; import * as MakerPSMSampler from '../test/generated-artifacts/MakerPSMSampler.json';
@ -58,6 +59,7 @@ export const artifacts = {
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact, ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
Eth2DaiSampler: Eth2DaiSampler as ContractArtifact, Eth2DaiSampler: Eth2DaiSampler as ContractArtifact,
FakeTaker: FakeTaker as ContractArtifact, FakeTaker: FakeTaker as ContractArtifact,
KyberDmmSampler: KyberDmmSampler as ContractArtifact,
KyberSampler: KyberSampler as ContractArtifact, KyberSampler: KyberSampler as ContractArtifact,
LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact, LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact,
MStableSampler: MStableSampler as ContractArtifact, MStableSampler: MStableSampler as ContractArtifact,

View File

@ -395,7 +395,7 @@ describe('MarketOperationUtils tests', () => {
[ERC20BridgeSource.Uniswap]: { router: randomAddress() }, [ERC20BridgeSource.Uniswap]: { router: randomAddress() },
[ERC20BridgeSource.Eth2Dai]: { router: randomAddress() }, [ERC20BridgeSource.Eth2Dai]: { router: randomAddress() },
[ERC20BridgeSource.MakerPsm]: {}, [ERC20BridgeSource.MakerPsm]: {},
[ERC20BridgeSource.KyberDmm]: { tokenAddressPath: [] }, [ERC20BridgeSource.KyberDmm]: { tokenAddressPath: [], router: randomAddress(), poolsPath: [] },
}; };
const DEFAULT_OPS = { const DEFAULT_OPS = {

View File

@ -27,6 +27,7 @@ export * from '../test/generated-wrappers/i_shell';
export * from '../test/generated-wrappers/i_smoothy'; export * from '../test/generated-wrappers/i_smoothy';
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/kyber_dmm_sampler';
export * from '../test/generated-wrappers/kyber_sampler'; export * from '../test/generated-wrappers/kyber_sampler';
export * from '../test/generated-wrappers/liquidity_provider_sampler'; export * from '../test/generated-wrappers/liquidity_provider_sampler';
export * from '../test/generated-wrappers/m_stable_sampler'; export * from '../test/generated-wrappers/m_stable_sampler';

View File

@ -30,6 +30,7 @@
"test/generated-artifacts/ISmoothy.json", "test/generated-artifacts/ISmoothy.json",
"test/generated-artifacts/IUniswapExchangeQuotes.json", "test/generated-artifacts/IUniswapExchangeQuotes.json",
"test/generated-artifacts/IUniswapV2Router01.json", "test/generated-artifacts/IUniswapV2Router01.json",
"test/generated-artifacts/KyberDmmSampler.json",
"test/generated-artifacts/KyberSampler.json", "test/generated-artifacts/KyberSampler.json",
"test/generated-artifacts/LiquidityProviderSampler.json", "test/generated-artifacts/LiquidityProviderSampler.json",
"test/generated-artifacts/MStableSampler.json", "test/generated-artifacts/MStableSampler.json",

View File

@ -128,6 +128,7 @@ export enum BridgeProtocol {
MakerPsm, MakerPsm,
BalancerV2, BalancerV2,
UniswapV3, UniswapV3,
KyberDmm,
} }
// tslint:enable: enum-naming // tslint:enable: enum-naming