feat: Swerve Finance and SushiSwap (#2698)
* feat: Swerve Finance * export SwerveFillData * test and CHANGELOG * feat: Sushiswap (#2700) * feat: SushiSwap * Changelog * fix tests * Deployed SushiSwap bridge * Fix test * IGNORED_EXCESSIVE_TYPES
This commit is contained in:
parent
08ae43aad3
commit
630108ccb6
136
contracts/asset-proxy/contracts/src/bridges/SushiSwapBridge.sol
Normal file
136
contracts/asset-proxy/contracts/src/bridges/SushiSwapBridge.sol
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/interfaces/IEtherToken.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
|
||||||
|
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/LibAddressArray.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||||
|
import "../interfaces/IUniswapV2Router01.sol";
|
||||||
|
import "../interfaces/IERC20Bridge.sol";
|
||||||
|
|
||||||
|
|
||||||
|
// solhint-disable space-after-comma
|
||||||
|
// solhint-disable not-rely-on-time
|
||||||
|
contract SushiSwapBridge is
|
||||||
|
IERC20Bridge,
|
||||||
|
IWallet,
|
||||||
|
DeploymentConstants
|
||||||
|
{
|
||||||
|
struct TransferState {
|
||||||
|
address[] path;
|
||||||
|
address router;
|
||||||
|
uint256 fromTokenBalance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Callback for `IERC20Bridge`. Tries to buy `amount` of
|
||||||
|
/// `toTokenAddress` tokens by selling the entirety of the `fromTokenAddress`
|
||||||
|
/// token encoded in the bridge data.
|
||||||
|
/// @param toTokenAddress The token to buy and transfer to `to`.
|
||||||
|
/// @param from The maker (this contract).
|
||||||
|
/// @param to The recipient of the bought tokens.
|
||||||
|
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
|
||||||
|
/// @param bridgeData The abi-encoded path of token addresses. Last element must be toTokenAddress
|
||||||
|
/// @return success The magic bytes if successful.
|
||||||
|
function bridgeTransferFrom(
|
||||||
|
address toTokenAddress,
|
||||||
|
address from,
|
||||||
|
address to,
|
||||||
|
uint256 amount,
|
||||||
|
bytes calldata bridgeData
|
||||||
|
)
|
||||||
|
external
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
|
// hold variables to get around stack depth limitations
|
||||||
|
TransferState memory state;
|
||||||
|
|
||||||
|
// Decode the bridge data to get the `fromTokenAddress`.
|
||||||
|
// solhint-disable indent
|
||||||
|
(state.path, state.router) = abi.decode(bridgeData, (address[], address));
|
||||||
|
// solhint-enable indent
|
||||||
|
|
||||||
|
require(state.path.length >= 2, "SushiSwapBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
||||||
|
require(state.path[state.path.length - 1] == toTokenAddress, "SushiSwapBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN");
|
||||||
|
|
||||||
|
// Just transfer the tokens if they're the same.
|
||||||
|
if (state.path[0] == toTokenAddress) {
|
||||||
|
LibERC20Token.transfer(state.path[0], to, amount);
|
||||||
|
return BRIDGE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get our balance of `fromTokenAddress` token.
|
||||||
|
state.fromTokenBalance = IERC20Token(state.path[0]).balanceOf(address(this));
|
||||||
|
|
||||||
|
// Grant the SushiSwap router an allowance.
|
||||||
|
LibERC20Token.approveIfBelow(
|
||||||
|
state.path[0],
|
||||||
|
state.router,
|
||||||
|
state.fromTokenBalance
|
||||||
|
);
|
||||||
|
|
||||||
|
// Buy as much `toTokenAddress` token with `fromTokenAddress` token
|
||||||
|
// and transfer it to `to`.
|
||||||
|
IUniswapV2Router01 router = IUniswapV2Router01(state.router);
|
||||||
|
uint[] memory amounts = router.swapExactTokensForTokens(
|
||||||
|
// Sell all tokens we hold.
|
||||||
|
state.fromTokenBalance,
|
||||||
|
// Minimum buy amount.
|
||||||
|
amount,
|
||||||
|
// Convert `fromTokenAddress` to `toTokenAddress`.
|
||||||
|
state.path,
|
||||||
|
// Recipient is `to`.
|
||||||
|
to,
|
||||||
|
// Expires after this block.
|
||||||
|
block.timestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
emit ERC20BridgeTransfer(
|
||||||
|
// input token
|
||||||
|
state.path[0],
|
||||||
|
// output token
|
||||||
|
toTokenAddress,
|
||||||
|
// input token amount
|
||||||
|
state.fromTokenBalance,
|
||||||
|
// output token amount
|
||||||
|
amounts[amounts.length - 1],
|
||||||
|
from,
|
||||||
|
to
|
||||||
|
);
|
||||||
|
|
||||||
|
return BRIDGE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
|
||||||
|
/// and sign for itself in orders. Always succeeds.
|
||||||
|
/// @return magicValue Success bytes, always.
|
||||||
|
function isValidSignature(
|
||||||
|
bytes32,
|
||||||
|
bytes calldata
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (bytes4 magicValue)
|
||||||
|
{
|
||||||
|
return LEGACY_WALLET_MAGIC_VALUE;
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@
|
|||||||
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|StaticCallProxy|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
|
"abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|StaticCallProxy|SushiSwapBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
|
||||||
"abis: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."
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -44,6 +44,7 @@ import * as MStableBridge from '../generated-artifacts/MStableBridge.json';
|
|||||||
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
|
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
|
||||||
import * as Ownable from '../generated-artifacts/Ownable.json';
|
import * as Ownable from '../generated-artifacts/Ownable.json';
|
||||||
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
|
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
|
||||||
|
import * as SushiSwapBridge from '../generated-artifacts/SushiSwapBridge.json';
|
||||||
import * as TestBancorBridge from '../generated-artifacts/TestBancorBridge.json';
|
import * as TestBancorBridge from '../generated-artifacts/TestBancorBridge.json';
|
||||||
import * as TestChaiBridge from '../generated-artifacts/TestChaiBridge.json';
|
import * as TestChaiBridge from '../generated-artifacts/TestChaiBridge.json';
|
||||||
import * as TestDexForwarderBridge from '../generated-artifacts/TestDexForwarderBridge.json';
|
import * as TestDexForwarderBridge from '../generated-artifacts/TestDexForwarderBridge.json';
|
||||||
@ -77,6 +78,7 @@ export const artifacts = {
|
|||||||
MStableBridge: MStableBridge as ContractArtifact,
|
MStableBridge: MStableBridge as ContractArtifact,
|
||||||
MixinGasToken: MixinGasToken as ContractArtifact,
|
MixinGasToken: MixinGasToken as ContractArtifact,
|
||||||
MooniswapBridge: MooniswapBridge as ContractArtifact,
|
MooniswapBridge: MooniswapBridge as ContractArtifact,
|
||||||
|
SushiSwapBridge: SushiSwapBridge as ContractArtifact,
|
||||||
UniswapBridge: UniswapBridge as ContractArtifact,
|
UniswapBridge: UniswapBridge as ContractArtifact,
|
||||||
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
|
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
|
||||||
IAssetData: IAssetData as ContractArtifact,
|
IAssetData: IAssetData as ContractArtifact,
|
||||||
|
@ -42,6 +42,7 @@ export * from '../generated-wrappers/mooniswap_bridge';
|
|||||||
export * from '../generated-wrappers/multi_asset_proxy';
|
export * from '../generated-wrappers/multi_asset_proxy';
|
||||||
export * from '../generated-wrappers/ownable';
|
export * from '../generated-wrappers/ownable';
|
||||||
export * from '../generated-wrappers/static_call_proxy';
|
export * from '../generated-wrappers/static_call_proxy';
|
||||||
|
export * from '../generated-wrappers/sushi_swap_bridge';
|
||||||
export * from '../generated-wrappers/test_bancor_bridge';
|
export * from '../generated-wrappers/test_bancor_bridge';
|
||||||
export * from '../generated-wrappers/test_chai_bridge';
|
export * from '../generated-wrappers/test_chai_bridge';
|
||||||
export * from '../generated-wrappers/test_dex_forwarder_bridge';
|
export * from '../generated-wrappers/test_dex_forwarder_bridge';
|
||||||
|
@ -44,6 +44,7 @@ import * as MStableBridge from '../test/generated-artifacts/MStableBridge.json';
|
|||||||
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
|
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
|
||||||
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
import * as Ownable from '../test/generated-artifacts/Ownable.json';
|
||||||
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
|
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
|
||||||
|
import * as SushiSwapBridge from '../test/generated-artifacts/SushiSwapBridge.json';
|
||||||
import * as TestBancorBridge from '../test/generated-artifacts/TestBancorBridge.json';
|
import * as TestBancorBridge from '../test/generated-artifacts/TestBancorBridge.json';
|
||||||
import * as TestChaiBridge from '../test/generated-artifacts/TestChaiBridge.json';
|
import * as TestChaiBridge from '../test/generated-artifacts/TestChaiBridge.json';
|
||||||
import * as TestDexForwarderBridge from '../test/generated-artifacts/TestDexForwarderBridge.json';
|
import * as TestDexForwarderBridge from '../test/generated-artifacts/TestDexForwarderBridge.json';
|
||||||
@ -77,6 +78,7 @@ export const artifacts = {
|
|||||||
MStableBridge: MStableBridge as ContractArtifact,
|
MStableBridge: MStableBridge as ContractArtifact,
|
||||||
MixinGasToken: MixinGasToken as ContractArtifact,
|
MixinGasToken: MixinGasToken as ContractArtifact,
|
||||||
MooniswapBridge: MooniswapBridge as ContractArtifact,
|
MooniswapBridge: MooniswapBridge as ContractArtifact,
|
||||||
|
SushiSwapBridge: SushiSwapBridge as ContractArtifact,
|
||||||
UniswapBridge: UniswapBridge as ContractArtifact,
|
UniswapBridge: UniswapBridge as ContractArtifact,
|
||||||
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
|
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
|
||||||
IAssetData: IAssetData as ContractArtifact,
|
IAssetData: IAssetData as ContractArtifact,
|
||||||
|
@ -42,6 +42,7 @@ export * from '../test/generated-wrappers/mooniswap_bridge';
|
|||||||
export * from '../test/generated-wrappers/multi_asset_proxy';
|
export * from '../test/generated-wrappers/multi_asset_proxy';
|
||||||
export * from '../test/generated-wrappers/ownable';
|
export * from '../test/generated-wrappers/ownable';
|
||||||
export * from '../test/generated-wrappers/static_call_proxy';
|
export * from '../test/generated-wrappers/static_call_proxy';
|
||||||
|
export * from '../test/generated-wrappers/sushi_swap_bridge';
|
||||||
export * from '../test/generated-wrappers/test_bancor_bridge';
|
export * from '../test/generated-wrappers/test_bancor_bridge';
|
||||||
export * from '../test/generated-wrappers/test_chai_bridge';
|
export * from '../test/generated-wrappers/test_chai_bridge';
|
||||||
export * from '../test/generated-wrappers/test_dex_forwarder_bridge';
|
export * from '../test/generated-wrappers/test_dex_forwarder_bridge';
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"generated-artifacts/MultiAssetProxy.json",
|
"generated-artifacts/MultiAssetProxy.json",
|
||||||
"generated-artifacts/Ownable.json",
|
"generated-artifacts/Ownable.json",
|
||||||
"generated-artifacts/StaticCallProxy.json",
|
"generated-artifacts/StaticCallProxy.json",
|
||||||
|
"generated-artifacts/SushiSwapBridge.json",
|
||||||
"generated-artifacts/TestBancorBridge.json",
|
"generated-artifacts/TestBancorBridge.json",
|
||||||
"generated-artifacts/TestChaiBridge.json",
|
"generated-artifacts/TestChaiBridge.json",
|
||||||
"generated-artifacts/TestDexForwarderBridge.json",
|
"generated-artifacts/TestDexForwarderBridge.json",
|
||||||
@ -93,6 +94,7 @@
|
|||||||
"test/generated-artifacts/MultiAssetProxy.json",
|
"test/generated-artifacts/MultiAssetProxy.json",
|
||||||
"test/generated-artifacts/Ownable.json",
|
"test/generated-artifacts/Ownable.json",
|
||||||
"test/generated-artifacts/StaticCallProxy.json",
|
"test/generated-artifacts/StaticCallProxy.json",
|
||||||
|
"test/generated-artifacts/SushiSwapBridge.json",
|
||||||
"test/generated-artifacts/TestBancorBridge.json",
|
"test/generated-artifacts/TestBancorBridge.json",
|
||||||
"test/generated-artifacts/TestChaiBridge.json",
|
"test/generated-artifacts/TestChaiBridge.json",
|
||||||
"test/generated-artifacts/TestDexForwarderBridge.json",
|
"test/generated-artifacts/TestDexForwarderBridge.json",
|
||||||
|
@ -288,11 +288,11 @@ contract DeploymentConstants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Mooniswap registry address.
|
/// @dev An overridable way to retrieve the Mooniswap registry address.
|
||||||
/// @return musd The Mooniswap registry address.
|
/// @return registry The Mooniswap registry address.
|
||||||
function _getMooniswapAddress()
|
function _getMooniswapAddress()
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (address registry)
|
returns (address)
|
||||||
{
|
{
|
||||||
return MOONISWAP_REGISTRY;
|
return MOONISWAP_REGISTRY;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,14 @@
|
|||||||
{
|
{
|
||||||
"note": "Return Mooniswap pool in sampler and encode it in bridge data",
|
"note": "Return Mooniswap pool in sampler and encode it in bridge data",
|
||||||
"pr": 2692
|
"pr": 2692
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `Swerve`",
|
||||||
|
"pr": 2698
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added `SushiSwap`",
|
||||||
|
"pr": 2698
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -28,9 +28,10 @@ import "./MultiBridgeSampler.sol";
|
|||||||
import "./MStableSampler.sol";
|
import "./MStableSampler.sol";
|
||||||
import "./MooniswapSampler.sol";
|
import "./MooniswapSampler.sol";
|
||||||
import "./NativeOrderSampler.sol";
|
import "./NativeOrderSampler.sol";
|
||||||
|
import "./SushiSwapSampler.sol";
|
||||||
|
import "./TwoHopSampler.sol";
|
||||||
import "./UniswapSampler.sol";
|
import "./UniswapSampler.sol";
|
||||||
import "./UniswapV2Sampler.sol";
|
import "./UniswapV2Sampler.sol";
|
||||||
import "./TwoHopSampler.sol";
|
|
||||||
|
|
||||||
|
|
||||||
contract ERC20BridgeSampler is
|
contract ERC20BridgeSampler is
|
||||||
@ -43,6 +44,7 @@ contract ERC20BridgeSampler is
|
|||||||
MooniswapSampler,
|
MooniswapSampler,
|
||||||
MultiBridgeSampler,
|
MultiBridgeSampler,
|
||||||
NativeOrderSampler,
|
NativeOrderSampler,
|
||||||
|
SushiSwapSampler,
|
||||||
TwoHopSampler,
|
TwoHopSampler,
|
||||||
UniswapSampler,
|
UniswapSampler,
|
||||||
UniswapV2Sampler
|
UniswapV2Sampler
|
||||||
|
103
packages/asset-swapper/contracts/src/SushiSwapSampler.sol
Normal file
103
packages/asset-swapper/contracts/src/SushiSwapSampler.sol
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2019 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.5.9;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
|
||||||
|
import "./interfaces/IUniswapV2Router01.sol";
|
||||||
|
|
||||||
|
|
||||||
|
contract SushiSwapSampler is
|
||||||
|
DeploymentConstants
|
||||||
|
{
|
||||||
|
/// @dev Gas limit for SushiSwap calls.
|
||||||
|
uint256 constant private SUSHISWAP_CALL_GAS = 150e3; // 150k
|
||||||
|
|
||||||
|
/// @dev Sample sell quotes from SushiSwap.
|
||||||
|
/// @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 makerTokenAmounts Maker amounts bought at each taker token
|
||||||
|
/// amount.
|
||||||
|
function sampleSellsFromSushiSwap(
|
||||||
|
address router,
|
||||||
|
address[] memory path,
|
||||||
|
uint256[] memory takerTokenAmounts
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (uint256[] memory makerTokenAmounts)
|
||||||
|
{
|
||||||
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
|
(bool didSucceed, bytes memory resultData) =
|
||||||
|
router.staticcall.gas(SUSHISWAP_CALL_GAS)(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IUniswapV2Router01(0).getAmountsOut.selector,
|
||||||
|
takerTokenAmounts[i],
|
||||||
|
path
|
||||||
|
));
|
||||||
|
uint256 buyAmount = 0;
|
||||||
|
if (didSucceed) {
|
||||||
|
// solhint-disable-next-line indent
|
||||||
|
buyAmount = abi.decode(resultData, (uint256[]))[path.length - 1];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
makerTokenAmounts[i] = buyAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Sample buy quotes from SushiSwap
|
||||||
|
/// @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 takerTokenAmounts Taker amounts sold at each maker token
|
||||||
|
/// amount.
|
||||||
|
function sampleBuysFromSushiSwap(
|
||||||
|
address router,
|
||||||
|
address[] memory path,
|
||||||
|
uint256[] memory makerTokenAmounts
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (uint256[] memory takerTokenAmounts)
|
||||||
|
{
|
||||||
|
uint256 numSamples = makerTokenAmounts.length;
|
||||||
|
takerTokenAmounts = new uint256[](numSamples);
|
||||||
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
|
(bool didSucceed, bytes memory resultData) =
|
||||||
|
router.staticcall.gas(SUSHISWAP_CALL_GAS)(
|
||||||
|
abi.encodeWithSelector(
|
||||||
|
IUniswapV2Router01(0).getAmountsIn.selector,
|
||||||
|
makerTokenAmounts[i],
|
||||||
|
path
|
||||||
|
));
|
||||||
|
uint256 sellAmount = 0;
|
||||||
|
if (didSucceed) {
|
||||||
|
// solhint-disable-next-line indent
|
||||||
|
sellAmount = abi.decode(resultData, (uint256[]))[0];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
takerTokenAmounts[i] = sellAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,7 +38,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
|
"publicInterfaceContracts": "ERC20BridgeSampler,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/@(ApproximateBuys|BalancerSampler|CurveSampler|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|ILiquidityProvider|ILiquidityProviderRegistry|IMStable|IMooniswap|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalancerSampler|CurveSampler|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|ILiquidityProvider|ILiquidityProviderRegistry|IMStable|IMooniswap|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
|
||||||
"postpublish": {
|
"postpublish": {
|
||||||
"assets": []
|
"assets": []
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ export {
|
|||||||
MarketOperation,
|
MarketOperation,
|
||||||
MarketSellSwapQuote,
|
MarketSellSwapQuote,
|
||||||
MockedRfqtFirmQuoteResponse,
|
MockedRfqtFirmQuoteResponse,
|
||||||
|
OrderPrunerPermittedFeeTypes,
|
||||||
RfqtMakerAssetOfferings,
|
RfqtMakerAssetOfferings,
|
||||||
RfqtRequestOpts,
|
RfqtRequestOpts,
|
||||||
SamplerOverrides,
|
SamplerOverrides,
|
||||||
@ -148,6 +149,9 @@ export {
|
|||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
SourceInfo,
|
SourceInfo,
|
||||||
SourceQuoteOperation,
|
SourceQuoteOperation,
|
||||||
|
SushiSwapFillData,
|
||||||
|
SwerveFillData,
|
||||||
|
SwerveInfo,
|
||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './utils/market_operation_utils/types';
|
} from './utils/market_operation_utils/types';
|
||||||
|
@ -17,6 +17,8 @@ export const SELL_SOURCES = [
|
|||||||
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports batch requests
|
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports batch requests
|
||||||
ERC20BridgeSource.MStable,
|
ERC20BridgeSource.MStable,
|
||||||
ERC20BridgeSource.Mooniswap,
|
ERC20BridgeSource.Mooniswap,
|
||||||
|
ERC20BridgeSource.Swerve,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +34,8 @@ export const BUY_SOURCES = [
|
|||||||
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports buy quotes
|
// ERC20BridgeSource.Bancor, // FIXME: Disabled until Bancor SDK supports buy quotes
|
||||||
ERC20BridgeSource.MStable,
|
ERC20BridgeSource.MStable,
|
||||||
ERC20BridgeSource.Mooniswap,
|
ERC20BridgeSource.Mooniswap,
|
||||||
|
ERC20BridgeSource.Swerve,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
|
||||||
@ -132,6 +136,20 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
export const MAINNET_SWERVE_INFOS: { [name: string]: CurveInfo } = {
|
||||||
|
swUSD: {
|
||||||
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
|
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
|
poolAddress: '0x329239599afB305DA0A2eC69c58F8a6697F9F88d',
|
||||||
|
tokens: [
|
||||||
|
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||||
|
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||||
|
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
|
'0x0000000000085d4780b73119b644ae5ecd22b376',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const MAINNET_KYBER_RESERVE_IDS: { [name: string]: string } = {
|
export const MAINNET_KYBER_RESERVE_IDS: { [name: string]: string } = {
|
||||||
Reserve1: '0xff4b796265722046707200000000000000000000000000000000000000000000',
|
Reserve1: '0xff4b796265722046707200000000000000000000000000000000000000000000',
|
||||||
@ -169,6 +187,8 @@ export const MAINNET_KYBER_TOKEN_RESERVE_IDS: { [token: string]: string } = {
|
|||||||
'0xaa42414e44000000000000000000000000000000000000000000000000000000',
|
'0xaa42414e44000000000000000000000000000000000000000000000000000000',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MAINNET_SUSHI_SWAP_ROUTER = '0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F';
|
||||||
|
|
||||||
export const ERC20_PROXY_ID = '0xf47261b0';
|
export const ERC20_PROXY_ID = '0xf47261b0';
|
||||||
export const WALLET_SIGNATURE = '0x04';
|
export const WALLET_SIGNATURE = '0x04';
|
||||||
export const ONE_ETHER = new BigNumber(1e18);
|
export const ONE_ETHER = new BigNumber(1e18);
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import { MAINNET_CURVE_INFOS } from './constants';
|
import { MAINNET_CURVE_INFOS, MAINNET_SWERVE_INFOS } from './constants';
|
||||||
import { CurveInfo } from './types';
|
import { CurveInfo, SwerveInfo } from './types';
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
// tslint:disable completed-docs
|
||||||
export function getCurveInfosForPair(takerToken: string, makerToken: string): CurveInfo[] {
|
export function getCurveInfosForPair(takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
return Object.values(MAINNET_CURVE_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
|
return Object.values(MAINNET_CURVE_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSwerveInfosForPair(takerToken: string, makerToken: string): SwerveInfo[] {
|
||||||
|
return Object.values(MAINNET_SWERVE_INFOS).filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)));
|
||||||
|
}
|
||||||
|
@ -35,6 +35,8 @@ import {
|
|||||||
NativeCollapsedFill,
|
NativeCollapsedFill,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
OrderDomain,
|
OrderDomain,
|
||||||
|
SushiSwapFillData,
|
||||||
|
SwerveFillData,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
@ -222,8 +224,12 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath
|
|||||||
return opts.contractAddresses.uniswapBridge;
|
return opts.contractAddresses.uniswapBridge;
|
||||||
case ERC20BridgeSource.UniswapV2:
|
case ERC20BridgeSource.UniswapV2:
|
||||||
return opts.contractAddresses.uniswapV2Bridge;
|
return opts.contractAddresses.uniswapV2Bridge;
|
||||||
|
case ERC20BridgeSource.SushiSwap:
|
||||||
|
return opts.contractAddresses.sushiswapBridge;
|
||||||
case ERC20BridgeSource.Curve:
|
case ERC20BridgeSource.Curve:
|
||||||
return opts.contractAddresses.curveBridge;
|
return opts.contractAddresses.curveBridge;
|
||||||
|
case ERC20BridgeSource.Swerve:
|
||||||
|
return opts.contractAddresses.curveBridge;
|
||||||
case ERC20BridgeSource.Bancor:
|
case ERC20BridgeSource.Bancor:
|
||||||
return opts.contractAddresses.bancorBridge;
|
return opts.contractAddresses.bancorBridge;
|
||||||
case ERC20BridgeSource.Balancer:
|
case ERC20BridgeSource.Balancer:
|
||||||
@ -266,6 +272,20 @@ function createBridgeOrder(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case ERC20BridgeSource.Swerve:
|
||||||
|
const swerveFillData = (fill as CollapsedFill<SwerveFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
|
makerToken,
|
||||||
|
bridgeAddress,
|
||||||
|
createCurveBridgeData(
|
||||||
|
swerveFillData.pool.poolAddress,
|
||||||
|
swerveFillData.pool.exchangeFunctionSelector,
|
||||||
|
takerToken,
|
||||||
|
swerveFillData.fromTokenIdx,
|
||||||
|
swerveFillData.toTokenIdx,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
break;
|
||||||
case ERC20BridgeSource.Balancer:
|
case ERC20BridgeSource.Balancer:
|
||||||
const balancerFillData = (fill as CollapsedFill<BalancerFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
const balancerFillData = (fill as CollapsedFill<BalancerFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
@ -290,6 +310,14 @@ function createBridgeOrder(
|
|||||||
createUniswapV2BridgeData(uniswapV2FillData.tokenAddressPath),
|
createUniswapV2BridgeData(uniswapV2FillData.tokenAddressPath),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case ERC20BridgeSource.SushiSwap:
|
||||||
|
const sushiSwapFillData = (fill as CollapsedFill<SushiSwapFillData>).fillData!; // tslint:disable-line:no-non-null-assertion
|
||||||
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
|
makerToken,
|
||||||
|
bridgeAddress,
|
||||||
|
createSushiSwapBridgeData(sushiSwapFillData.tokenAddressPath, sushiSwapFillData.router),
|
||||||
|
);
|
||||||
|
break;
|
||||||
case ERC20BridgeSource.MultiBridge:
|
case ERC20BridgeSource.MultiBridge:
|
||||||
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
makerAssetData = assetDataUtils.encodeERC20BridgeAssetData(
|
||||||
makerToken,
|
makerToken,
|
||||||
@ -431,25 +459,24 @@ function createCurveBridgeData(
|
|||||||
fromTokenIdx: number,
|
fromTokenIdx: number,
|
||||||
toTokenIdx: number,
|
toTokenIdx: number,
|
||||||
): string {
|
): string {
|
||||||
const curveBridgeDataEncoder = AbiEncoder.create([
|
const encoder = AbiEncoder.create([
|
||||||
{ name: 'curveAddress', type: 'address' },
|
{ name: 'curveAddress', type: 'address' },
|
||||||
{ name: 'exchangeFunctionSelector', type: 'bytes4' },
|
{ name: 'exchangeFunctionSelector', type: 'bytes4' },
|
||||||
{ name: 'fromTokenAddress', type: 'address' },
|
{ name: 'fromTokenAddress', type: 'address' },
|
||||||
{ name: 'fromTokenIdx', type: 'int128' },
|
{ name: 'fromTokenIdx', type: 'int128' },
|
||||||
{ name: 'toTokenIdx', type: 'int128' },
|
{ name: 'toTokenIdx', type: 'int128' },
|
||||||
]);
|
]);
|
||||||
return curveBridgeDataEncoder.encode([
|
return encoder.encode([curveAddress, exchangeFunctionSelector, takerToken, fromTokenIdx, toTokenIdx]);
|
||||||
curveAddress,
|
|
||||||
exchangeFunctionSelector,
|
|
||||||
takerToken,
|
|
||||||
fromTokenIdx,
|
|
||||||
toTokenIdx,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createUniswapV2BridgeData(tokenAddressPath: string[]): string {
|
function createUniswapV2BridgeData(tokenAddressPath: string[]): string {
|
||||||
const uniswapV2BridgeDataEncoder = AbiEncoder.create('(address[])');
|
const encoder = AbiEncoder.create('(address[])');
|
||||||
return uniswapV2BridgeDataEncoder.encode([tokenAddressPath]);
|
return encoder.encode([tokenAddressPath]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSushiSwapBridgeData(tokenAddressPath: string[], router: string): string {
|
||||||
|
const encoder = AbiEncoder.create('(address[],address)');
|
||||||
|
return encoder.encode([tokenAddressPath, router]);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSlippedBridgeAssetAmounts(fill: CollapsedFill, opts: CreateOrderFromPathOpts): [BigNumber, BigNumber] {
|
function getSlippedBridgeAssetAmounts(fill: CollapsedFill, opts: CreateOrderFromPathOpts): [BigNumber, BigNumber] {
|
||||||
|
@ -6,8 +6,8 @@ import { ERC20BridgeSamplerContract } from '../../wrappers';
|
|||||||
|
|
||||||
import { BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils';
|
import { BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils';
|
||||||
import { BancorService } from './bancor_service';
|
import { BancorService } from './bancor_service';
|
||||||
import { MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants';
|
import { MAINNET_SUSHI_SWAP_ROUTER, MAX_UINT256, NULL_BYTES, ZERO_AMOUNT } from './constants';
|
||||||
import { getCurveInfosForPair } from './curve_utils';
|
import { getCurveInfosForPair, getSwerveInfosForPair } from './curve_utils';
|
||||||
import { getKyberReserveIdsForPair } from './kyber_utils';
|
import { getKyberReserveIdsForPair } from './kyber_utils';
|
||||||
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
import { getMultiBridgeIntermediateToken } from './multibridge_utils';
|
||||||
import { getIntermediateTokens } from './multihop_utils';
|
import { getIntermediateTokens } from './multihop_utils';
|
||||||
@ -27,6 +27,9 @@ import {
|
|||||||
MultiBridgeFillData,
|
MultiBridgeFillData,
|
||||||
MultiHopFillData,
|
MultiHopFillData,
|
||||||
SourceQuoteOperation,
|
SourceQuoteOperation,
|
||||||
|
SushiSwapFillData,
|
||||||
|
SwerveFillData,
|
||||||
|
SwerveInfo,
|
||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './types';
|
} from './types';
|
||||||
@ -315,6 +318,62 @@ export class SamplerOperations {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSwerveSellQuotes(
|
||||||
|
pool: SwerveInfo,
|
||||||
|
fromTokenIdx: number,
|
||||||
|
toTokenIdx: number,
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<SwerveFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.Swerve,
|
||||||
|
fillData: {
|
||||||
|
pool,
|
||||||
|
fromTokenIdx,
|
||||||
|
toTokenIdx,
|
||||||
|
},
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleSellsFromCurve,
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
poolAddress: pool.poolAddress,
|
||||||
|
sellQuoteFunctionSelector: pool.sellQuoteFunctionSelector,
|
||||||
|
buyQuoteFunctionSelector: pool.buyQuoteFunctionSelector,
|
||||||
|
},
|
||||||
|
new BigNumber(fromTokenIdx),
|
||||||
|
new BigNumber(toTokenIdx),
|
||||||
|
takerFillAmounts,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSwerveBuyQuotes(
|
||||||
|
pool: SwerveInfo,
|
||||||
|
fromTokenIdx: number,
|
||||||
|
toTokenIdx: number,
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<SwerveFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.Swerve,
|
||||||
|
fillData: {
|
||||||
|
pool,
|
||||||
|
fromTokenIdx,
|
||||||
|
toTokenIdx,
|
||||||
|
},
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleBuysFromCurve,
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
poolAddress: pool.poolAddress,
|
||||||
|
sellQuoteFunctionSelector: pool.sellQuoteFunctionSelector,
|
||||||
|
buyQuoteFunctionSelector: pool.buyQuoteFunctionSelector,
|
||||||
|
},
|
||||||
|
new BigNumber(fromTokenIdx),
|
||||||
|
new BigNumber(toTokenIdx),
|
||||||
|
makerFillAmounts,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public getBalancerSellQuotes(
|
public getBalancerSellQuotes(
|
||||||
poolAddress: string,
|
poolAddress: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
@ -621,6 +680,32 @@ export class SamplerOperations {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSushiSwapSellQuotes(
|
||||||
|
tokenAddressPath: string[],
|
||||||
|
takerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<SushiSwapFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.SushiSwap,
|
||||||
|
fillData: { tokenAddressPath, router: MAINNET_SUSHI_SWAP_ROUTER },
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleSellsFromSushiSwap,
|
||||||
|
params: [MAINNET_SUSHI_SWAP_ROUTER, tokenAddressPath, takerFillAmounts],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSushiSwapBuyQuotes(
|
||||||
|
tokenAddressPath: string[],
|
||||||
|
makerFillAmounts: BigNumber[],
|
||||||
|
): SourceQuoteOperation<SushiSwapFillData> {
|
||||||
|
return new SamplerContractOperation({
|
||||||
|
source: ERC20BridgeSource.SushiSwap,
|
||||||
|
fillData: { tokenAddressPath, router: MAINNET_SUSHI_SWAP_ROUTER },
|
||||||
|
contract: this._samplerContract,
|
||||||
|
function: this._samplerContract.sampleBuysFromSushiSwap,
|
||||||
|
params: [MAINNET_SUSHI_SWAP_ROUTER, tokenAddressPath, makerFillAmounts],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public getMedianSellRate(
|
public getMedianSellRate(
|
||||||
sources: ERC20BridgeSource[],
|
sources: ERC20BridgeSource[],
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
@ -784,6 +869,17 @@ export class SamplerOperations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ops;
|
return ops;
|
||||||
|
case ERC20BridgeSource.SushiSwap:
|
||||||
|
const sushiOps = [this.getSushiSwapSellQuotes([takerToken, makerToken], takerFillAmounts)];
|
||||||
|
if (takerToken !== wethAddress && makerToken !== wethAddress) {
|
||||||
|
sushiOps.push(
|
||||||
|
this.getSushiSwapSellQuotes(
|
||||||
|
[takerToken, wethAddress, makerToken],
|
||||||
|
takerFillAmounts,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return sushiOps;
|
||||||
case ERC20BridgeSource.Kyber:
|
case ERC20BridgeSource.Kyber:
|
||||||
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
||||||
this.getKyberSellQuotes(reserveId, makerToken, takerToken, takerFillAmounts),
|
this.getKyberSellQuotes(reserveId, makerToken, takerToken, takerFillAmounts),
|
||||||
@ -797,6 +893,15 @@ export class SamplerOperations {
|
|||||||
takerFillAmounts,
|
takerFillAmounts,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
case ERC20BridgeSource.Swerve:
|
||||||
|
return getSwerveInfosForPair(takerToken, makerToken).map(pool =>
|
||||||
|
this.getSwerveSellQuotes(
|
||||||
|
pool,
|
||||||
|
pool.tokens.indexOf(takerToken),
|
||||||
|
pool.tokens.indexOf(makerToken),
|
||||||
|
takerFillAmounts,
|
||||||
|
),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.LiquidityProvider:
|
case ERC20BridgeSource.LiquidityProvider:
|
||||||
if (liquidityProviderRegistryAddress === undefined) {
|
if (liquidityProviderRegistryAddress === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -865,6 +970,14 @@ export class SamplerOperations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ops;
|
return ops;
|
||||||
|
case ERC20BridgeSource.SushiSwap:
|
||||||
|
const sushiOps = [this.getSushiSwapBuyQuotes([takerToken, makerToken], makerFillAmounts)];
|
||||||
|
if (takerToken !== wethAddress && makerToken !== wethAddress) {
|
||||||
|
sushiOps.push(
|
||||||
|
this.getSushiSwapBuyQuotes([takerToken, wethAddress, makerToken], makerFillAmounts),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return sushiOps;
|
||||||
case ERC20BridgeSource.Kyber:
|
case ERC20BridgeSource.Kyber:
|
||||||
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
return getKyberReserveIdsForPair(takerToken, makerToken).map(reserveId =>
|
||||||
this.getKyberBuyQuotes(reserveId, makerToken, takerToken, makerFillAmounts),
|
this.getKyberBuyQuotes(reserveId, makerToken, takerToken, makerFillAmounts),
|
||||||
@ -878,6 +991,15 @@ export class SamplerOperations {
|
|||||||
makerFillAmounts,
|
makerFillAmounts,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
case ERC20BridgeSource.Swerve:
|
||||||
|
return getSwerveInfosForPair(takerToken, makerToken).map(pool =>
|
||||||
|
this.getSwerveBuyQuotes(
|
||||||
|
pool,
|
||||||
|
pool.tokens.indexOf(takerToken),
|
||||||
|
pool.tokens.indexOf(makerToken),
|
||||||
|
makerFillAmounts,
|
||||||
|
),
|
||||||
|
);
|
||||||
case ERC20BridgeSource.LiquidityProvider:
|
case ERC20BridgeSource.LiquidityProvider:
|
||||||
if (liquidityProviderRegistryAddress === undefined) {
|
if (liquidityProviderRegistryAddress === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -41,6 +41,8 @@ export enum ERC20BridgeSource {
|
|||||||
MStable = 'mStable',
|
MStable = 'mStable',
|
||||||
Mooniswap = 'Mooniswap',
|
Mooniswap = 'Mooniswap',
|
||||||
MultiHop = 'MultiHop',
|
MultiHop = 'MultiHop',
|
||||||
|
Swerve = 'Swerve',
|
||||||
|
SushiSwap = 'SushiSwap',
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable: enum-naming
|
// tslint:disable: enum-naming
|
||||||
@ -69,6 +71,8 @@ export interface CurveInfo {
|
|||||||
tokens: string[];
|
tokens: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SwerveInfo extends CurveInfo {}
|
||||||
|
|
||||||
// Internal `fillData` field for `Fill` objects.
|
// Internal `fillData` field for `Fill` objects.
|
||||||
export interface FillData {}
|
export interface FillData {}
|
||||||
|
|
||||||
@ -88,6 +92,12 @@ export interface CurveFillData extends FillData {
|
|||||||
curve: CurveInfo;
|
curve: CurveInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SwerveFillData extends FillData {
|
||||||
|
fromTokenIdx: number;
|
||||||
|
toTokenIdx: number;
|
||||||
|
pool: SwerveInfo;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BalancerFillData extends FillData {
|
export interface BalancerFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
@ -96,6 +106,10 @@ export interface UniswapV2FillData extends FillData {
|
|||||||
tokenAddressPath: string[];
|
tokenAddressPath: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SushiSwapFillData extends UniswapV2FillData {
|
||||||
|
router: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface LiquidityProviderFillData extends FillData {
|
export interface LiquidityProviderFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
@ -103,6 +117,7 @@ export interface LiquidityProviderFillData extends FillData {
|
|||||||
export interface MultiBridgeFillData extends FillData {
|
export interface MultiBridgeFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BancorFillData extends FillData {
|
export interface BancorFillData extends FillData {
|
||||||
path: string[];
|
path: string[];
|
||||||
networkAddress: string;
|
networkAddress: string;
|
||||||
|
@ -30,6 +30,7 @@ import * as MStableSampler from '../test/generated-artifacts/MStableSampler.json
|
|||||||
import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json';
|
import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json';
|
||||||
import * as NativeOrderSampler from '../test/generated-artifacts/NativeOrderSampler.json';
|
import * as NativeOrderSampler from '../test/generated-artifacts/NativeOrderSampler.json';
|
||||||
import * as SamplerUtils from '../test/generated-artifacts/SamplerUtils.json';
|
import * as SamplerUtils from '../test/generated-artifacts/SamplerUtils.json';
|
||||||
|
import * as SushiSwapSampler from '../test/generated-artifacts/SushiSwapSampler.json';
|
||||||
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json';
|
||||||
import * as TestNativeOrderSampler from '../test/generated-artifacts/TestNativeOrderSampler.json';
|
import * as TestNativeOrderSampler from '../test/generated-artifacts/TestNativeOrderSampler.json';
|
||||||
import * as TwoHopSampler from '../test/generated-artifacts/TwoHopSampler.json';
|
import * as TwoHopSampler from '../test/generated-artifacts/TwoHopSampler.json';
|
||||||
@ -49,6 +50,7 @@ export const artifacts = {
|
|||||||
MultiBridgeSampler: MultiBridgeSampler as ContractArtifact,
|
MultiBridgeSampler: MultiBridgeSampler as ContractArtifact,
|
||||||
NativeOrderSampler: NativeOrderSampler as ContractArtifact,
|
NativeOrderSampler: NativeOrderSampler as ContractArtifact,
|
||||||
SamplerUtils: SamplerUtils as ContractArtifact,
|
SamplerUtils: SamplerUtils as ContractArtifact,
|
||||||
|
SushiSwapSampler: SushiSwapSampler as ContractArtifact,
|
||||||
TwoHopSampler: TwoHopSampler as ContractArtifact,
|
TwoHopSampler: TwoHopSampler as ContractArtifact,
|
||||||
UniswapSampler: UniswapSampler as ContractArtifact,
|
UniswapSampler: UniswapSampler as ContractArtifact,
|
||||||
UniswapV2Sampler: UniswapV2Sampler as ContractArtifact,
|
UniswapV2Sampler: UniswapV2Sampler as ContractArtifact,
|
||||||
|
@ -27,6 +27,16 @@ const MAKER_TOKEN = randomAddress();
|
|||||||
const TAKER_TOKEN = randomAddress();
|
const TAKER_TOKEN = randomAddress();
|
||||||
const MAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(MAKER_TOKEN);
|
const MAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(MAKER_TOKEN);
|
||||||
const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN);
|
const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN);
|
||||||
|
const DEFAULT_EXCLUDED = [
|
||||||
|
ERC20BridgeSource.UniswapV2,
|
||||||
|
ERC20BridgeSource.Curve,
|
||||||
|
ERC20BridgeSource.Balancer,
|
||||||
|
ERC20BridgeSource.MStable,
|
||||||
|
ERC20BridgeSource.Mooniswap,
|
||||||
|
ERC20BridgeSource.Bancor,
|
||||||
|
ERC20BridgeSource.Swerve,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
|
];
|
||||||
|
|
||||||
// tslint:disable: custom-no-magic-numbers promise-function-async
|
// tslint:disable: custom-no-magic-numbers promise-function-async
|
||||||
describe('MarketOperationUtils tests', () => {
|
describe('MarketOperationUtils tests', () => {
|
||||||
@ -80,6 +90,8 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
return ERC20BridgeSource.MStable;
|
return ERC20BridgeSource.MStable;
|
||||||
case contractAddresses.mooniswapBridge.toLowerCase():
|
case contractAddresses.mooniswapBridge.toLowerCase():
|
||||||
return ERC20BridgeSource.Mooniswap;
|
return ERC20BridgeSource.Mooniswap;
|
||||||
|
case contractAddresses.sushiswapBridge.toLowerCase():
|
||||||
|
return ERC20BridgeSource.SushiSwap;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -238,11 +250,11 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[source: string]: Numberish[];
|
[source: string]: Numberish[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_RATES: RatesBySource = {
|
const ZERO_RATES: RatesBySource = {
|
||||||
[ERC20BridgeSource.Native]: createDecreasingRates(NUM_SAMPLES),
|
[ERC20BridgeSource.Native]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Eth2Dai]: createDecreasingRates(NUM_SAMPLES),
|
[ERC20BridgeSource.Eth2Dai]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Kyber]: createDecreasingRates(NUM_SAMPLES),
|
[ERC20BridgeSource.Uniswap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Uniswap]: createDecreasingRates(NUM_SAMPLES),
|
[ERC20BridgeSource.Kyber]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.UniswapV2]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.UniswapV2]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Balancer]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.Balancer]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Bancor]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.Bancor]: _.times(NUM_SAMPLES, () => 0),
|
||||||
@ -251,6 +263,15 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.MultiBridge]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.MultiBridge]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.MStable]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.MStable]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Mooniswap]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.Mooniswap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.Swerve]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.SushiSwap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_RATES: RatesBySource = {
|
||||||
|
...ZERO_RATES,
|
||||||
|
[ERC20BridgeSource.Native]: createDecreasingRates(NUM_SAMPLES),
|
||||||
|
[ERC20BridgeSource.Eth2Dai]: createDecreasingRates(NUM_SAMPLES),
|
||||||
|
[ERC20BridgeSource.Uniswap]: createDecreasingRates(NUM_SAMPLES),
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FillDataBySource {
|
interface FillDataBySource {
|
||||||
@ -273,7 +294,19 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
fromTokenIdx: 0,
|
fromTokenIdx: 0,
|
||||||
toTokenIdx: 1,
|
toTokenIdx: 1,
|
||||||
},
|
},
|
||||||
|
[ERC20BridgeSource.Swerve]: {
|
||||||
|
pool: {
|
||||||
|
poolAddress: randomAddress(),
|
||||||
|
tokens: [TAKER_TOKEN, MAKER_TOKEN],
|
||||||
|
exchangeFunctionSelector: hexUtils.random(4),
|
||||||
|
sellQuoteFunctionSelector: hexUtils.random(4),
|
||||||
|
buyQuoteFunctionSelector: hexUtils.random(4),
|
||||||
|
},
|
||||||
|
fromTokenIdx: 0,
|
||||||
|
toTokenIdx: 1,
|
||||||
|
},
|
||||||
[ERC20BridgeSource.LiquidityProvider]: { poolAddress: randomAddress() },
|
[ERC20BridgeSource.LiquidityProvider]: { poolAddress: randomAddress() },
|
||||||
|
[ERC20BridgeSource.SushiSwap]: { tokenAddressPath: [] },
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_OPS = {
|
const DEFAULT_OPS = {
|
||||||
@ -416,14 +449,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sampleDistributionBase: 1,
|
sampleDistributionBase: 1,
|
||||||
bridgeSlippage: 0,
|
bridgeSlippage: 0,
|
||||||
maxFallbackSlippage: 100,
|
maxFallbackSlippage: 100,
|
||||||
excludedSources: [
|
excludedSources: DEFAULT_EXCLUDED,
|
||||||
ERC20BridgeSource.UniswapV2,
|
|
||||||
ERC20BridgeSource.Curve,
|
|
||||||
ERC20BridgeSource.Balancer,
|
|
||||||
ERC20BridgeSource.MStable,
|
|
||||||
ERC20BridgeSource.Mooniswap,
|
|
||||||
ERC20BridgeSource.Bancor,
|
|
||||||
],
|
|
||||||
allowFallback: false,
|
allowFallback: false,
|
||||||
shouldBatchBridgeOrders: false,
|
shouldBatchBridgeOrders: false,
|
||||||
};
|
};
|
||||||
@ -583,7 +609,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can mix convex sources', async () => {
|
it('can mix convex sources', async () => {
|
||||||
const rates: RatesBySource = {};
|
const rates: RatesBySource = { ...DEFAULT_RATES };
|
||||||
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
|
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
|
||||||
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
|
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
|
||||||
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
|
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
|
||||||
@ -852,14 +878,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
sampleDistributionBase: 1,
|
sampleDistributionBase: 1,
|
||||||
bridgeSlippage: 0,
|
bridgeSlippage: 0,
|
||||||
maxFallbackSlippage: 100,
|
maxFallbackSlippage: 100,
|
||||||
excludedSources: [
|
excludedSources: DEFAULT_EXCLUDED,
|
||||||
ERC20BridgeSource.Kyber,
|
|
||||||
ERC20BridgeSource.UniswapV2,
|
|
||||||
ERC20BridgeSource.Curve,
|
|
||||||
ERC20BridgeSource.Balancer,
|
|
||||||
ERC20BridgeSource.MStable,
|
|
||||||
ERC20BridgeSource.Mooniswap,
|
|
||||||
],
|
|
||||||
allowFallback: false,
|
allowFallback: false,
|
||||||
shouldBatchBridgeOrders: false,
|
shouldBatchBridgeOrders: false,
|
||||||
};
|
};
|
||||||
@ -1019,7 +1038,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can mix convex sources', async () => {
|
it('can mix convex sources', async () => {
|
||||||
const rates: RatesBySource = {};
|
const rates: RatesBySource = { ...ZERO_RATES };
|
||||||
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
|
rates[ERC20BridgeSource.Native] = [0.4, 0.3, 0.2, 0.1];
|
||||||
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
|
rates[ERC20BridgeSource.Uniswap] = [0.5, 0.05, 0.05, 0.05];
|
||||||
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
|
rates[ERC20BridgeSource.Eth2Dai] = [0.6, 0.05, 0.05, 0.05];
|
||||||
@ -1049,6 +1068,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
// dropping their effective rates.
|
// dropping their effective rates.
|
||||||
const nativeFeeRate = 0.06;
|
const nativeFeeRate = 0.06;
|
||||||
const rates: RatesBySource = {
|
const rates: RatesBySource = {
|
||||||
|
...ZERO_RATES,
|
||||||
[ERC20BridgeSource.Native]: [1, 0.99, 0.98, 0.97], // Effectively [0.94, ~0.93, ~0.92, ~0.91]
|
[ERC20BridgeSource.Native]: [1, 0.99, 0.98, 0.97], // Effectively [0.94, ~0.93, ~0.92, ~0.91]
|
||||||
[ERC20BridgeSource.Uniswap]: [0.96, 0.1, 0.1, 0.1],
|
[ERC20BridgeSource.Uniswap]: [0.96, 0.1, 0.1, 0.1],
|
||||||
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
|
[ERC20BridgeSource.Eth2Dai]: [0.95, 0.1, 0.1, 0.1],
|
||||||
@ -1086,6 +1106,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
// dropping its effective rates.
|
// dropping its effective rates.
|
||||||
const uniswapFeeRate = 0.2;
|
const uniswapFeeRate = 0.2;
|
||||||
const rates: RatesBySource = {
|
const rates: RatesBySource = {
|
||||||
|
...ZERO_RATES,
|
||||||
[ERC20BridgeSource.Native]: [0.95, 0.1, 0.1, 0.1],
|
[ERC20BridgeSource.Native]: [0.95, 0.1, 0.1, 0.1],
|
||||||
// Effectively [0.8, ~0.5, ~0, ~0]
|
// Effectively [0.8, ~0.5, ~0, ~0]
|
||||||
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
|
[ERC20BridgeSource.Uniswap]: [1, 0.7, 0.2, 0.2],
|
||||||
@ -1118,7 +1139,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('fallback orders use different sources', async () => {
|
it('fallback orders use different sources', async () => {
|
||||||
const rates: RatesBySource = {};
|
const rates: RatesBySource = { ...ZERO_RATES };
|
||||||
rates[ERC20BridgeSource.Native] = [0.9, 0.8, 0.5, 0.5];
|
rates[ERC20BridgeSource.Native] = [0.9, 0.8, 0.5, 0.5];
|
||||||
rates[ERC20BridgeSource.Uniswap] = [0.6, 0.05, 0.01, 0.01];
|
rates[ERC20BridgeSource.Uniswap] = [0.6, 0.05, 0.01, 0.01];
|
||||||
rates[ERC20BridgeSource.Eth2Dai] = [0.4, 0.3, 0.01, 0.01];
|
rates[ERC20BridgeSource.Eth2Dai] = [0.4, 0.3, 0.01, 0.01];
|
||||||
@ -1138,7 +1159,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('does not create a fallback if below maxFallbackSlippage', async () => {
|
it('does not create a fallback if below maxFallbackSlippage', async () => {
|
||||||
const rates: RatesBySource = {};
|
const rates: RatesBySource = { ...ZERO_RATES };
|
||||||
rates[ERC20BridgeSource.Native] = [1, 1, 0.01, 0.01];
|
rates[ERC20BridgeSource.Native] = [1, 1, 0.01, 0.01];
|
||||||
rates[ERC20BridgeSource.Uniswap] = [1, 1, 0.01, 0.01];
|
rates[ERC20BridgeSource.Uniswap] = [1, 1, 0.01, 0.01];
|
||||||
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.49, 0.49, 0.49];
|
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.49, 0.49, 0.49];
|
||||||
@ -1159,7 +1180,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('batches contiguous bridge sources', async () => {
|
it('batches contiguous bridge sources', async () => {
|
||||||
const rates: RatesBySource = {};
|
const rates: RatesBySource = { ...ZERO_RATES };
|
||||||
rates[ERC20BridgeSource.Native] = [0.5, 0.01, 0.01, 0.01];
|
rates[ERC20BridgeSource.Native] = [0.5, 0.01, 0.01, 0.01];
|
||||||
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.02, 0.01, 0.01];
|
rates[ERC20BridgeSource.Eth2Dai] = [0.49, 0.02, 0.01, 0.01];
|
||||||
rates[ERC20BridgeSource.Uniswap] = [0.48, 0.01, 0.01, 0.01];
|
rates[ERC20BridgeSource.Uniswap] = [0.48, 0.01, 0.01, 0.01];
|
||||||
|
@ -28,6 +28,7 @@ export * from '../test/generated-wrappers/mooniswap_sampler';
|
|||||||
export * from '../test/generated-wrappers/multi_bridge_sampler';
|
export * from '../test/generated-wrappers/multi_bridge_sampler';
|
||||||
export * from '../test/generated-wrappers/native_order_sampler';
|
export * from '../test/generated-wrappers/native_order_sampler';
|
||||||
export * from '../test/generated-wrappers/sampler_utils';
|
export * from '../test/generated-wrappers/sampler_utils';
|
||||||
|
export * from '../test/generated-wrappers/sushi_swap_sampler';
|
||||||
export * from '../test/generated-wrappers/test_erc20_bridge_sampler';
|
export * from '../test/generated-wrappers/test_erc20_bridge_sampler';
|
||||||
export * from '../test/generated-wrappers/test_native_order_sampler';
|
export * from '../test/generated-wrappers/test_native_order_sampler';
|
||||||
export * from '../test/generated-wrappers/two_hop_sampler';
|
export * from '../test/generated-wrappers/two_hop_sampler';
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"test/generated-artifacts/MultiBridgeSampler.json",
|
"test/generated-artifacts/MultiBridgeSampler.json",
|
||||||
"test/generated-artifacts/NativeOrderSampler.json",
|
"test/generated-artifacts/NativeOrderSampler.json",
|
||||||
"test/generated-artifacts/SamplerUtils.json",
|
"test/generated-artifacts/SamplerUtils.json",
|
||||||
|
"test/generated-artifacts/SushiSwapSampler.json",
|
||||||
"test/generated-artifacts/TestERC20BridgeSampler.json",
|
"test/generated-artifacts/TestERC20BridgeSampler.json",
|
||||||
"test/generated-artifacts/TestNativeOrderSampler.json",
|
"test/generated-artifacts/TestNativeOrderSampler.json",
|
||||||
"test/generated-artifacts/TwoHopSampler.json",
|
"test/generated-artifacts/TwoHopSampler.json",
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"mStableBridge": "0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3",
|
"mStableBridge": "0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3",
|
||||||
"mooniswapBridge": "0x02b7eca484ad960fca3f7709e0b2ac81eec3069c",
|
"mooniswapBridge": "0x02b7eca484ad960fca3f7709e0b2ac81eec3069c",
|
||||||
|
"sushiswapBridge": "0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0x68c0bb685099dc7cb5c5ce2b26185945b357383e",
|
"wethTransformer": "0x68c0bb685099dc7cb5c5ce2b26185945b357383e",
|
||||||
"payTakerTransformer": "0x49b9df2c58491764cf40cb052dd4243df63622c7",
|
"payTakerTransformer": "0x49b9df2c58491764cf40cb052dd4243df63622c7",
|
||||||
@ -92,6 +93,7 @@
|
|||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
|
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
|
||||||
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
|
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
|
||||||
@ -142,6 +144,7 @@
|
|||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
|
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
|
||||||
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
|
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
|
||||||
@ -192,6 +195,7 @@
|
|||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0x9ce35b5ee9e710535e3988e3f8731d9ca9dba17d",
|
"wethTransformer": "0x9ce35b5ee9e710535e3988e3f8731d9ca9dba17d",
|
||||||
"payTakerTransformer": "0x5a53e7b02a83aa9f60ccf4e424f0442c255bc977",
|
"payTakerTransformer": "0x5a53e7b02a83aa9f60ccf4e424f0442c255bc977",
|
||||||
@ -242,6 +246,7 @@
|
|||||||
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
|
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
|
||||||
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
"mStableBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5",
|
"wethTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5",
|
||||||
"payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3",
|
"payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3",
|
||||||
|
@ -43,6 +43,7 @@ export interface ContractAddresses {
|
|||||||
exchangeProxyFlashWallet: string;
|
exchangeProxyFlashWallet: string;
|
||||||
mStableBridge: string;
|
mStableBridge: string;
|
||||||
mooniswapBridge: string;
|
mooniswapBridge: string;
|
||||||
|
sushiswapBridge: string;
|
||||||
transformers: {
|
transformers: {
|
||||||
wethTransformer: string;
|
wethTransformer: string;
|
||||||
payTakerTransformer: string;
|
payTakerTransformer: string;
|
||||||
|
@ -400,6 +400,7 @@ export async function runMigrationsAsync(
|
|||||||
exchangeProxyGovernor: NULL_ADDRESS,
|
exchangeProxyGovernor: NULL_ADDRESS,
|
||||||
mStableBridge: NULL_ADDRESS,
|
mStableBridge: NULL_ADDRESS,
|
||||||
mooniswapBridge: NULL_ADDRESS,
|
mooniswapBridge: NULL_ADDRESS,
|
||||||
|
sushiswapBridge: NULL_ADDRESS,
|
||||||
exchangeProxy: exchangeProxy.address,
|
exchangeProxy: exchangeProxy.address,
|
||||||
exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress,
|
exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress,
|
||||||
exchangeProxyTransformerDeployer: txDefaults.from,
|
exchangeProxyTransformerDeployer: txDefaults.from,
|
||||||
|
@ -70,6 +70,7 @@ export const docGenConfigs: DocGenConfigs = {
|
|||||||
'MultiAssetData',
|
'MultiAssetData',
|
||||||
'StaticCallAssetData',
|
'StaticCallAssetData',
|
||||||
'MultiAssetDataWithRecursiveDecoding',
|
'MultiAssetDataWithRecursiveDecoding',
|
||||||
|
'OrderPrunerPermittedFeeTypes',
|
||||||
],
|
],
|
||||||
// Some libraries only export types. In those cases, we cannot check if the exported types are part of the
|
// Some libraries only export types. In those cases, we cannot check if the exported types are part of the
|
||||||
// "exported public interface". Thus we add them here and skip those checks.
|
// "exported public interface". Thus we add them here and skip those checks.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user