feat: Clipper (#299)
* feat: Clipper * feat: Curve tricrypto2 (#302) * Scope down the token list search space for Clipper * update deployed addresses
This commit is contained in:
parent
59eabec71e
commit
a35af11981
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.27.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `Clipper` as a custom liquidity source"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.26.0",
|
"version": "0.26.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -25,6 +25,7 @@ import "./BridgeProtocols.sol";
|
|||||||
import "./mixins/MixinBalancer.sol";
|
import "./mixins/MixinBalancer.sol";
|
||||||
import "./mixins/MixinBalancerV2.sol";
|
import "./mixins/MixinBalancerV2.sol";
|
||||||
import "./mixins/MixinBancor.sol";
|
import "./mixins/MixinBancor.sol";
|
||||||
|
import "./mixins/MixinClipper.sol";
|
||||||
import "./mixins/MixinCoFiX.sol";
|
import "./mixins/MixinCoFiX.sol";
|
||||||
import "./mixins/MixinCurve.sol";
|
import "./mixins/MixinCurve.sol";
|
||||||
import "./mixins/MixinCurveV2.sol";
|
import "./mixins/MixinCurveV2.sol";
|
||||||
@ -50,6 +51,7 @@ contract BridgeAdapter is
|
|||||||
MixinBalancer,
|
MixinBalancer,
|
||||||
MixinBalancerV2,
|
MixinBalancerV2,
|
||||||
MixinBancor,
|
MixinBancor,
|
||||||
|
MixinClipper,
|
||||||
MixinCoFiX,
|
MixinCoFiX,
|
||||||
MixinCurve,
|
MixinCurve,
|
||||||
MixinCurveV2,
|
MixinCurveV2,
|
||||||
@ -75,6 +77,7 @@ contract BridgeAdapter is
|
|||||||
MixinBalancer()
|
MixinBalancer()
|
||||||
MixinBalancerV2()
|
MixinBalancerV2()
|
||||||
MixinBancor(weth)
|
MixinBancor(weth)
|
||||||
|
MixinClipper(weth)
|
||||||
MixinCoFiX()
|
MixinCoFiX()
|
||||||
MixinCurve(weth)
|
MixinCurve(weth)
|
||||||
MixinCurveV2()
|
MixinCurveV2()
|
||||||
@ -245,6 +248,13 @@ contract BridgeAdapter is
|
|||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
|
} else if (protocolId == BridgeProtocols.CLIPPER) {
|
||||||
|
boughtAmount = _tradeClipper(
|
||||||
|
sellToken,
|
||||||
|
buyToken,
|
||||||
|
sellAmount,
|
||||||
|
order.bridgeData
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
boughtAmount = _tradeZeroExBridge(
|
boughtAmount = _tradeZeroExBridge(
|
||||||
sellToken,
|
sellToken,
|
||||||
|
@ -49,4 +49,5 @@ library BridgeProtocols {
|
|||||||
uint128 internal constant KYBERDMM = 19;
|
uint128 internal constant KYBERDMM = 19;
|
||||||
uint128 internal constant CURVEV2 = 20;
|
uint128 internal constant CURVEV2 = 20;
|
||||||
uint128 internal constant LIDO = 21;
|
uint128 internal constant LIDO = 21;
|
||||||
|
uint128 internal constant CLIPPER = 22;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,148 @@
|
|||||||
|
// 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 "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||||
|
import "../IBridgeAdapter.sol";
|
||||||
|
import "../../../vendor/ILiquidityProvider.sol";
|
||||||
|
|
||||||
|
contract MixinClipper {
|
||||||
|
|
||||||
|
using LibERC20TokenV06 for IERC20TokenV06;
|
||||||
|
|
||||||
|
/// @dev Mainnet address of the WETH contract.
|
||||||
|
IEtherTokenV06 private immutable WETH;
|
||||||
|
|
||||||
|
constructor(IEtherTokenV06 weth)
|
||||||
|
public
|
||||||
|
{
|
||||||
|
WETH = weth;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _tradeClipper(
|
||||||
|
IERC20TokenV06 sellToken,
|
||||||
|
IERC20TokenV06 buyToken,
|
||||||
|
uint256 sellAmount,
|
||||||
|
bytes memory bridgeData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns (uint256 boughtAmount)
|
||||||
|
{
|
||||||
|
// We can only use ETH with Clipper, no WETH available
|
||||||
|
(ILiquidityProvider clipper, bytes memory auxiliaryData) =
|
||||||
|
abi.decode(bridgeData, (ILiquidityProvider, bytes));
|
||||||
|
|
||||||
|
if (sellToken == WETH) {
|
||||||
|
boughtAmount = _executeSellEthForToken(
|
||||||
|
clipper,
|
||||||
|
buyToken,
|
||||||
|
sellAmount,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
} else if (buyToken == WETH) {
|
||||||
|
boughtAmount = _executeSellTokenForEth(
|
||||||
|
clipper,
|
||||||
|
sellToken,
|
||||||
|
sellAmount,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
boughtAmount = _executeSellTokenForToken(
|
||||||
|
clipper,
|
||||||
|
sellToken,
|
||||||
|
buyToken,
|
||||||
|
sellAmount,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return boughtAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _executeSellEthForToken(
|
||||||
|
ILiquidityProvider clipper,
|
||||||
|
IERC20TokenV06 buyToken,
|
||||||
|
uint256 sellAmount,
|
||||||
|
bytes memory auxiliaryData
|
||||||
|
)
|
||||||
|
private
|
||||||
|
returns (uint256 boughtAmount)
|
||||||
|
{
|
||||||
|
// Clipper requires ETH and doesn't support WETH
|
||||||
|
WETH.withdraw(sellAmount);
|
||||||
|
boughtAmount = clipper.sellEthForToken{ value: sellAmount }(
|
||||||
|
buyToken,
|
||||||
|
address(this),
|
||||||
|
1,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _executeSellTokenForEth(
|
||||||
|
ILiquidityProvider clipper,
|
||||||
|
IERC20TokenV06 sellToken,
|
||||||
|
uint256 sellAmount,
|
||||||
|
bytes memory auxiliaryData
|
||||||
|
)
|
||||||
|
private
|
||||||
|
returns (uint256 boughtAmount)
|
||||||
|
{
|
||||||
|
// Optimization: We can transfer the tokens into clipper rather than
|
||||||
|
// have an allowance updated
|
||||||
|
sellToken.compatTransfer(address(clipper), sellAmount);
|
||||||
|
|
||||||
|
boughtAmount = clipper.sellTokenForEth(
|
||||||
|
sellToken,
|
||||||
|
payable(address(this)),
|
||||||
|
1,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
|
||||||
|
// we want WETH for possible future trades
|
||||||
|
WETH.deposit{ value: boughtAmount }();
|
||||||
|
}
|
||||||
|
|
||||||
|
function _executeSellTokenForToken(
|
||||||
|
ILiquidityProvider clipper,
|
||||||
|
IERC20TokenV06 sellToken,
|
||||||
|
IERC20TokenV06 buyToken,
|
||||||
|
uint256 sellAmount,
|
||||||
|
bytes memory auxiliaryData
|
||||||
|
)
|
||||||
|
private
|
||||||
|
returns (uint256 boughtAmount)
|
||||||
|
{
|
||||||
|
// Optimization: We can transfer the tokens into clipper rather than
|
||||||
|
// have an allowance updated
|
||||||
|
sellToken.compatTransfer(address(clipper), sellAmount);
|
||||||
|
|
||||||
|
boughtAmount = clipper.sellTokenForToken(
|
||||||
|
sellToken,
|
||||||
|
buyToken,
|
||||||
|
address(this),
|
||||||
|
1,
|
||||||
|
auxiliaryData
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -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,OtcOrdersFeature,IOtcOrdersFeature",
|
"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,OtcOrdersFeature,IOtcOrdersFeature",
|
||||||
"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|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|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|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|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|IOtcOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IUniswapV3Feature|IUniswapV3Pool|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOtcOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBalancerV2|MixinBancor|MixinClipper|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinCurveV2|MixinDodo|MixinDodoV2|MixinKyber|MixinKyberDmm|MixinLido|MixinMStable|MixinMakerPSM|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinUniswapV3|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OtcOrdersFeature|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|TestNoEthRecipient|TestOrderSignerRegistryWithContractWallet|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestUniswapV3Factory|TestUniswapV3Feature|TestUniswapV3Pool|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|UniswapV3Feature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -82,6 +82,7 @@ import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransa
|
|||||||
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
|
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
|
||||||
import * as MixinBalancerV2 from '../test/generated-artifacts/MixinBalancerV2.json';
|
import * as MixinBalancerV2 from '../test/generated-artifacts/MixinBalancerV2.json';
|
||||||
import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json';
|
import * as MixinBancor from '../test/generated-artifacts/MixinBancor.json';
|
||||||
|
import * as MixinClipper from '../test/generated-artifacts/MixinClipper.json';
|
||||||
import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json';
|
import * as MixinCoFiX from '../test/generated-artifacts/MixinCoFiX.json';
|
||||||
import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json';
|
import * as MixinCryptoCom from '../test/generated-artifacts/MixinCryptoCom.json';
|
||||||
import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
|
import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
|
||||||
@ -257,6 +258,7 @@ export const artifacts = {
|
|||||||
MixinBalancer: MixinBalancer as ContractArtifact,
|
MixinBalancer: MixinBalancer as ContractArtifact,
|
||||||
MixinBalancerV2: MixinBalancerV2 as ContractArtifact,
|
MixinBalancerV2: MixinBalancerV2 as ContractArtifact,
|
||||||
MixinBancor: MixinBancor as ContractArtifact,
|
MixinBancor: MixinBancor as ContractArtifact,
|
||||||
|
MixinClipper: MixinClipper as ContractArtifact,
|
||||||
MixinCoFiX: MixinCoFiX as ContractArtifact,
|
MixinCoFiX: MixinCoFiX as ContractArtifact,
|
||||||
MixinCryptoCom: MixinCryptoCom as ContractArtifact,
|
MixinCryptoCom: MixinCryptoCom as ContractArtifact,
|
||||||
MixinCurve: MixinCurve as ContractArtifact,
|
MixinCurve: MixinCurve as ContractArtifact,
|
||||||
|
@ -80,6 +80,7 @@ export * from '../test/generated-wrappers/meta_transactions_feature';
|
|||||||
export * from '../test/generated-wrappers/mixin_balancer';
|
export * from '../test/generated-wrappers/mixin_balancer';
|
||||||
export * from '../test/generated-wrappers/mixin_balancer_v2';
|
export * from '../test/generated-wrappers/mixin_balancer_v2';
|
||||||
export * from '../test/generated-wrappers/mixin_bancor';
|
export * from '../test/generated-wrappers/mixin_bancor';
|
||||||
|
export * from '../test/generated-wrappers/mixin_clipper';
|
||||||
export * from '../test/generated-wrappers/mixin_co_fi_x';
|
export * from '../test/generated-wrappers/mixin_co_fi_x';
|
||||||
export * from '../test/generated-wrappers/mixin_crypto_com';
|
export * from '../test/generated-wrappers/mixin_crypto_com';
|
||||||
export * from '../test/generated-wrappers/mixin_curve';
|
export * from '../test/generated-wrappers/mixin_curve';
|
||||||
|
@ -113,6 +113,7 @@
|
|||||||
"test/generated-artifacts/MixinBalancer.json",
|
"test/generated-artifacts/MixinBalancer.json",
|
||||||
"test/generated-artifacts/MixinBalancerV2.json",
|
"test/generated-artifacts/MixinBalancerV2.json",
|
||||||
"test/generated-artifacts/MixinBancor.json",
|
"test/generated-artifacts/MixinBancor.json",
|
||||||
|
"test/generated-artifacts/MixinClipper.json",
|
||||||
"test/generated-artifacts/MixinCoFiX.json",
|
"test/generated-artifacts/MixinCoFiX.json",
|
||||||
"test/generated-artifacts/MixinCryptoCom.json",
|
"test/generated-artifacts/MixinCryptoCom.json",
|
||||||
"test/generated-artifacts/MixinCurve.json",
|
"test/generated-artifacts/MixinCurve.json",
|
||||||
|
@ -1,4 +1,17 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "16.24.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `Clipper` as a custom liquidity source",
|
||||||
|
"pr": 299
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `Curve` `Tricrypto2` and `ESD` v2",
|
||||||
|
"pr": 302
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "16.23.1",
|
"version": "16.23.1",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -98,6 +98,7 @@ export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
|
|||||||
ERC20BridgeSource.UniswapV3,
|
ERC20BridgeSource.UniswapV3,
|
||||||
ERC20BridgeSource.CurveV2,
|
ERC20BridgeSource.CurveV2,
|
||||||
ERC20BridgeSource.ShibaSwap,
|
ERC20BridgeSource.ShibaSwap,
|
||||||
|
ERC20BridgeSource.Clipper,
|
||||||
]),
|
]),
|
||||||
[ChainId.Ropsten]: new SourceFilters([
|
[ChainId.Ropsten]: new SourceFilters([
|
||||||
ERC20BridgeSource.Kyber,
|
ERC20BridgeSource.Kyber,
|
||||||
@ -198,6 +199,7 @@ export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
|
|||||||
ERC20BridgeSource.UniswapV3,
|
ERC20BridgeSource.UniswapV3,
|
||||||
ERC20BridgeSource.CurveV2,
|
ERC20BridgeSource.CurveV2,
|
||||||
ERC20BridgeSource.ShibaSwap,
|
ERC20BridgeSource.ShibaSwap,
|
||||||
|
ERC20BridgeSource.Clipper,
|
||||||
]),
|
]),
|
||||||
[ChainId.Ropsten]: new SourceFilters([
|
[ChainId.Ropsten]: new SourceFilters([
|
||||||
ERC20BridgeSource.Kyber,
|
ERC20BridgeSource.Kyber,
|
||||||
@ -373,6 +375,8 @@ export const MAINNET_TOKENS = {
|
|||||||
FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
|
FRAX: '0x853d955acef822db058eb8505911ed77f175b99e',
|
||||||
LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0',
|
LUSD: '0x5f98805a4e8be255a32880fdec7f6728c6568ba0',
|
||||||
FEI: '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
|
FEI: '0x956f47f50a910163d8bf957cf5846d573e7f87ca',
|
||||||
|
DSU: '0x605d26fbd5be761089281d5cec2ce86eea667109',
|
||||||
|
ESS: '0x24ae124c4cc33d6791f8e8b63520ed7107ac8b3e',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const BSC_TOKENS = {
|
export const BSC_TOKENS = {
|
||||||
@ -448,10 +452,12 @@ export const CURVE_POOLS = {
|
|||||||
FRAX: '0xd632f22692fac7611d2aa1c0d552930d43caed3b',
|
FRAX: '0xd632f22692fac7611d2aa1c0d552930d43caed3b',
|
||||||
LUSD: '0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca',
|
LUSD: '0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca',
|
||||||
BUSD: '0x4807862aa8b2bf68830e4c8dc86d0e9a998e085a',
|
BUSD: '0x4807862aa8b2bf68830e4c8dc86d0e9a998e085a',
|
||||||
|
DSU3CRV: '0x6ec80df362d7042c50d4469bcfbc174c9dd9109a',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURVE_V2_POOLS = {
|
export const CURVE_V2_POOLS = {
|
||||||
tricrypto: '0x80466c64868e1ab14a1ddf27a676c3fcbe638fe5',
|
tricrypto: '0x80466c64868e1ab14a1ddf27a676c3fcbe638fe5',
|
||||||
|
tricrypto2: '0xd51a44d3fae010294c616388b506acda1bfaae46',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURVE_POLYGON_POOLS = {
|
export const CURVE_POLYGON_POOLS = {
|
||||||
@ -847,6 +853,11 @@ export const CURVE_MAINNET_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
pool: CURVE_POOLS.ankreth,
|
pool: CURVE_POOLS.ankreth,
|
||||||
gasSchedule: 125e3,
|
gasSchedule: 125e3,
|
||||||
}),
|
}),
|
||||||
|
[CURVE_POOLS.DSU3CRV]: createCurveMetaTriPool({
|
||||||
|
tokens: [MAINNET_TOKENS.DSU],
|
||||||
|
pool: CURVE_POOLS.DSU3CRV,
|
||||||
|
gasSchedule: 387e3,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURVE_V2_MAINNET_INFOS: { [name: string]: CurveInfo } = {
|
export const CURVE_V2_MAINNET_INFOS: { [name: string]: CurveInfo } = {
|
||||||
@ -855,6 +866,11 @@ export const CURVE_V2_MAINNET_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
pool: CURVE_V2_POOLS.tricrypto,
|
pool: CURVE_V2_POOLS.tricrypto,
|
||||||
gasSchedule: 300e3,
|
gasSchedule: 300e3,
|
||||||
}),
|
}),
|
||||||
|
[CURVE_V2_POOLS.tricrypto2]: createCurveExchangeV2Pool({
|
||||||
|
tokens: [MAINNET_TOKENS.USDT, MAINNET_TOKENS.WBTC, MAINNET_TOKENS.WETH],
|
||||||
|
pool: CURVE_V2_POOLS.tricrypto2,
|
||||||
|
gasSchedule: 300e3,
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const CURVE_POLYGON_INFOS: { [name: string]: CurveInfo } = {
|
export const CURVE_POLYGON_INFOS: { [name: string]: CurveInfo } = {
|
||||||
@ -1410,6 +1426,22 @@ export const LIDO_INFO_BY_CHAIN = valueByChainId<LidoInfo>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const CLIPPER_INFO_BY_CHAIN = valueByChainId(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: {
|
||||||
|
poolAddress: '0xe82906b6b1b04f631d126c974af57a3a7b6a99d9',
|
||||||
|
tokens: [
|
||||||
|
MAINNET_TOKENS.WETH, // technically ETH but our sampler and mixin handle this
|
||||||
|
MAINNET_TOKENS.WBTC,
|
||||||
|
MAINNET_TOKENS.USDC,
|
||||||
|
MAINNET_TOKENS.USDT,
|
||||||
|
MAINNET_TOKENS.DAI,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ poolAddress: NULL_ADDRESS, tokens: [] },
|
||||||
|
);
|
||||||
|
|
||||||
export const BALANCER_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
|
export const BALANCER_SUBGRAPH_URL = 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer';
|
||||||
export const BALANCER_TOP_POOLS_FETCHED = 250;
|
export const BALANCER_TOP_POOLS_FETCHED = 250;
|
||||||
export const BALANCER_MAX_POOLS_FETCHED = 3;
|
export const BALANCER_MAX_POOLS_FETCHED = 3;
|
||||||
@ -1640,6 +1672,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
return gas;
|
return gas;
|
||||||
},
|
},
|
||||||
[ERC20BridgeSource.Lido]: () => 226e3,
|
[ERC20BridgeSource.Lido]: () => 226e3,
|
||||||
|
[ERC20BridgeSource.Clipper]: () => 170e3,
|
||||||
|
|
||||||
//
|
//
|
||||||
// BSC
|
// BSC
|
||||||
|
@ -3,7 +3,7 @@ import { AbiEncoder, BigNumber } from '@0x/utils';
|
|||||||
|
|
||||||
import { AssetSwapperContractAddresses, MarketOperation } from '../../types';
|
import { AssetSwapperContractAddresses, MarketOperation } from '../../types';
|
||||||
|
|
||||||
import { MAX_UINT256, ZERO_AMOUNT } from './constants';
|
import { MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants';
|
||||||
import {
|
import {
|
||||||
AggregationError,
|
AggregationError,
|
||||||
BalancerFillData,
|
BalancerFillData,
|
||||||
@ -180,6 +180,8 @@ export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): s
|
|||||||
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'IronSwap');
|
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'IronSwap');
|
||||||
case ERC20BridgeSource.ACryptos:
|
case ERC20BridgeSource.ACryptos:
|
||||||
return encodeBridgeSourceId(BridgeProtocol.Curve, 'ACryptoS');
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'ACryptoS');
|
||||||
|
case ERC20BridgeSource.Clipper:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.Clipper, 'Clipper');
|
||||||
default:
|
default:
|
||||||
throw new Error(AggregationError.NoBridgeForSource);
|
throw new Error(AggregationError.NoBridgeForSource);
|
||||||
}
|
}
|
||||||
@ -318,6 +320,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
|
|||||||
const lidoFillData = (order as OptimizedMarketBridgeOrder<LidoFillData>).fillData;
|
const lidoFillData = (order as OptimizedMarketBridgeOrder<LidoFillData>).fillData;
|
||||||
bridgeData = encoder.encode([lidoFillData.stEthTokenAddress]);
|
bridgeData = encoder.encode([lidoFillData.stEthTokenAddress]);
|
||||||
break;
|
break;
|
||||||
|
case ERC20BridgeSource.Clipper:
|
||||||
|
const clipperFillData = (order as OptimizedMarketBridgeOrder<LiquidityProviderFillData>).fillData;
|
||||||
|
bridgeData = encoder.encode([clipperFillData.poolAddress, NULL_BYTES]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(AggregationError.NoBridgeForSource);
|
throw new Error(AggregationError.NoBridgeForSource);
|
||||||
}
|
}
|
||||||
@ -475,6 +481,10 @@ export const BRIDGE_ENCODERS: {
|
|||||||
]),
|
]),
|
||||||
[ERC20BridgeSource.KyberDmm]: AbiEncoder.create('(address,address[],address[])'),
|
[ERC20BridgeSource.KyberDmm]: AbiEncoder.create('(address,address[],address[])'),
|
||||||
[ERC20BridgeSource.Lido]: AbiEncoder.create('(address)'),
|
[ERC20BridgeSource.Lido]: AbiEncoder.create('(address)'),
|
||||||
|
[ERC20BridgeSource.Clipper]: AbiEncoder.create([
|
||||||
|
{ name: 'provider', type: 'address' },
|
||||||
|
{ name: 'data', type: 'bytes' },
|
||||||
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {
|
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {
|
||||||
|
@ -20,6 +20,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
BALANCER_V2_VAULT_ADDRESS_BY_CHAIN,
|
BALANCER_V2_VAULT_ADDRESS_BY_CHAIN,
|
||||||
BANCOR_REGISTRY_BY_CHAIN_ID,
|
BANCOR_REGISTRY_BY_CHAIN_ID,
|
||||||
|
CLIPPER_INFO_BY_CHAIN,
|
||||||
DODOV1_CONFIG_BY_CHAIN_ID,
|
DODOV1_CONFIG_BY_CHAIN_ID,
|
||||||
DODOV2_FACTORIES_BY_CHAIN_ID,
|
DODOV2_FACTORIES_BY_CHAIN_ID,
|
||||||
KYBER_CONFIG_BY_CHAIN_ID,
|
KYBER_CONFIG_BY_CHAIN_ID,
|
||||||
@ -359,9 +360,10 @@ export class SamplerOperations {
|
|||||||
takerToken: string,
|
takerToken: string,
|
||||||
takerFillAmounts: BigNumber[],
|
takerFillAmounts: BigNumber[],
|
||||||
gasCost: number,
|
gasCost: number,
|
||||||
|
source: ERC20BridgeSource = ERC20BridgeSource.LiquidityProvider,
|
||||||
): SourceQuoteOperation<LiquidityProviderFillData> {
|
): SourceQuoteOperation<LiquidityProviderFillData> {
|
||||||
return new SamplerContractOperation({
|
return new SamplerContractOperation({
|
||||||
source: ERC20BridgeSource.LiquidityProvider,
|
source,
|
||||||
fillData: {
|
fillData: {
|
||||||
poolAddress: providerAddress,
|
poolAddress: providerAddress,
|
||||||
gasCost,
|
gasCost,
|
||||||
@ -378,9 +380,10 @@ export class SamplerOperations {
|
|||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerFillAmounts: BigNumber[],
|
makerFillAmounts: BigNumber[],
|
||||||
gasCost: number,
|
gasCost: number,
|
||||||
|
source: ERC20BridgeSource = ERC20BridgeSource.LiquidityProvider,
|
||||||
): SourceQuoteOperation<LiquidityProviderFillData> {
|
): SourceQuoteOperation<LiquidityProviderFillData> {
|
||||||
return new SamplerContractOperation({
|
return new SamplerContractOperation({
|
||||||
source: ERC20BridgeSource.LiquidityProvider,
|
source,
|
||||||
fillData: {
|
fillData: {
|
||||||
poolAddress: providerAddress,
|
poolAddress: providerAddress,
|
||||||
gasCost,
|
gasCost,
|
||||||
@ -1322,9 +1325,9 @@ export class SamplerOperations {
|
|||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
) || []
|
) || []
|
||||||
).map(poolAddress =>
|
).map(balancerPool =>
|
||||||
this.getBalancerSellQuotes(
|
this.getBalancerSellQuotes(
|
||||||
poolAddress,
|
balancerPool,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
takerFillAmounts,
|
takerFillAmounts,
|
||||||
@ -1358,9 +1361,9 @@ export class SamplerOperations {
|
|||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
) || []
|
) || []
|
||||||
).map(poolAddress =>
|
).map(creamPool =>
|
||||||
this.getBalancerSellQuotes(
|
this.getBalancerSellQuotes(
|
||||||
poolAddress,
|
creamPool,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerToken,
|
takerToken,
|
||||||
takerFillAmounts,
|
takerFillAmounts,
|
||||||
@ -1449,6 +1452,32 @@ export class SamplerOperations {
|
|||||||
|
|
||||||
return this.getLidoSellQuotes(lidoInfo, makerToken, takerToken, takerFillAmounts);
|
return this.getLidoSellQuotes(lidoInfo, makerToken, takerToken, takerFillAmounts);
|
||||||
}
|
}
|
||||||
|
case ERC20BridgeSource.Clipper:
|
||||||
|
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||||
|
this.chainId
|
||||||
|
];
|
||||||
|
if (
|
||||||
|
clipperPoolAddress === NULL_ADDRESS ||
|
||||||
|
!clipperTokens.includes(makerToken) ||
|
||||||
|
!clipperTokens.includes(takerToken)
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// Clipper requires WETH to be represented as address(0)
|
||||||
|
const adjustedMakerToken =
|
||||||
|
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||||
|
const adjustedTakerToken =
|
||||||
|
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||||
|
// Supports the PLP interface
|
||||||
|
return this.getLiquidityProviderSellQuotes(
|
||||||
|
clipperPoolAddress,
|
||||||
|
adjustedMakerToken,
|
||||||
|
adjustedTakerToken,
|
||||||
|
takerFillAmounts,
|
||||||
|
// tslint:disable-next-line: custom-no-magic-numbers
|
||||||
|
0, // Not used for Clipper
|
||||||
|
ERC20BridgeSource.Clipper,
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported sell sample source: ${source}`);
|
throw new Error(`Unsupported sell sample source: ${source}`);
|
||||||
}
|
}
|
||||||
@ -1718,6 +1747,32 @@ export class SamplerOperations {
|
|||||||
|
|
||||||
return this.getLidoBuyQuotes(lidoInfo, makerToken, takerToken, makerFillAmounts);
|
return this.getLidoBuyQuotes(lidoInfo, makerToken, takerToken, makerFillAmounts);
|
||||||
}
|
}
|
||||||
|
case ERC20BridgeSource.Clipper:
|
||||||
|
const { poolAddress: clipperPoolAddress, tokens: clipperTokens } = CLIPPER_INFO_BY_CHAIN[
|
||||||
|
this.chainId
|
||||||
|
];
|
||||||
|
if (
|
||||||
|
clipperPoolAddress === NULL_ADDRESS ||
|
||||||
|
!clipperTokens.includes(makerToken) ||
|
||||||
|
!clipperTokens.includes(takerToken)
|
||||||
|
) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
// Clipper requires WETH to be represented as address(0)
|
||||||
|
const adjustedMakerToken =
|
||||||
|
makerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : makerToken;
|
||||||
|
const adjustedTakerToken =
|
||||||
|
takerToken === NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId] ? NULL_ADDRESS : takerToken;
|
||||||
|
// Supports the PLP interface
|
||||||
|
return this.getLiquidityProviderBuyQuotes(
|
||||||
|
clipperPoolAddress,
|
||||||
|
adjustedMakerToken,
|
||||||
|
adjustedTakerToken,
|
||||||
|
makerFillAmounts,
|
||||||
|
// tslint:disable-next-line: custom-no-magic-numbers
|
||||||
|
0, // Not used for Clipper
|
||||||
|
ERC20BridgeSource.Clipper,
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported buy sample source: ${source}`);
|
throw new Error(`Unsupported buy sample source: ${source}`);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ export enum ERC20BridgeSource {
|
|||||||
CurveV2 = 'Curve_V2',
|
CurveV2 = 'Curve_V2',
|
||||||
Lido = 'Lido',
|
Lido = 'Lido',
|
||||||
ShibaSwap = 'ShibaSwap',
|
ShibaSwap = 'ShibaSwap',
|
||||||
|
Clipper = 'Clipper',
|
||||||
// BSC only
|
// BSC only
|
||||||
PancakeSwap = 'PancakeSwap',
|
PancakeSwap = 'PancakeSwap',
|
||||||
PancakeSwapV2 = 'PancakeSwap_V2',
|
PancakeSwapV2 = 'PancakeSwap_V2',
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "6.5.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Deployed `Clipper`",
|
||||||
|
"pr": 299
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "6.4.0",
|
"version": "6.4.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
"wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
|
"wethTransformer": "0xb2bc06a4efb20fc6553a69dbfa49b7be938034a7",
|
||||||
"payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
|
"payTakerTransformer": "0x4638a7ebe75b911b995d0ec73a81e4f85f41f24e",
|
||||||
"affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
|
"affiliateFeeTransformer": "0xda6d9fc5998f550a094585cf9171f0e8ee3ac59f",
|
||||||
"fillQuoteTransformer": "0x6dfdb2537683ce6101f9090a78197dd58c30bfac",
|
"fillQuoteTransformer": "0xb4fa284689c9784a60d840eb136bb16c5246191f",
|
||||||
"positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd"
|
"positiveSlippageFeeTransformer": "0xa9416ce1dbde8d331210c07b5c253d94ee4cc3fd"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.8.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add `Clipper`"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1624356181,
|
"timestamp": 1624356181,
|
||||||
"version": "1.7.2",
|
"version": "1.7.2",
|
||||||
|
@ -131,6 +131,7 @@ export enum BridgeProtocol {
|
|||||||
KyberDmm,
|
KyberDmm,
|
||||||
CurveV2,
|
CurveV2,
|
||||||
Lido,
|
Lido,
|
||||||
|
Clipper,
|
||||||
}
|
}
|
||||||
// tslint:enable: enum-naming
|
// tslint:enable: enum-naming
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user