bsc<->development rebase (#189)
* FQT: Pack Protocol/source name into source ID (#162) * `@0x/contracts-zero-ex`: Encode protocol ID and source name in bridge source ID `@0x/asset-swapper`: Use new bridge source ID encoding. * fix linter issues * contracts cleanup (#164) * `@0x/contracts-zero-ex`: Add PancakeSwapFeature * `@0x/contracts-zero-ex`: Remove tokenspender/allowance target/greedy tokens stuff.' `@0x/contract-addresses`: Add BSC addresses. Remove exchangeProxyAllowanceTarget. `@0x/migrations`: Remove exchangeProxyAllowanceTarget. * Update contracts/zero-ex/contracts/src/features/IPancakeSwapFeature.sol Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com> * `@0x/contracts-zero-ex`: Add sushiswap support to PancakeSwap * `@0x/contract-artifacts`: Regenerate artifacts `@0x/contract-wrappers`: Regenerate wrappers * `@0x/contract-addresses`: Add BSC addresses Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com> Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com> * feat: Better chain support (#163) * feat: Better chain support * feat: better chain support refactor deployment constants (#166) * proliferate the chainId * Refactor sampler to remove DeploymentConstants dependency and fixed addresses * Rework WETH out, replacing with address(0) * wat * hack DeploymentConstants for now * proliferate the chainId * Refactor sampler to remove DeploymentConstants dependency and fixed addresses * remove duped network addresses * Rework the bridge source encoder * Use the constants NATIVE_FEE_TOKEN in EP consumer * `@0x/contract-addresses`: Fix WBNB address (#170) Co-authored-by: Lawrence Forman <lawrence@0xproject.com> * multichain enable cakez vip (#171) * feat: Better chain support * feat: better chain support refactor deployment constants (#166) * proliferate the chainId * Refactor sampler to remove DeploymentConstants dependency and fixed addresses * Rework WETH out, replacing with address(0) * wat * hack DeploymentConstants for now * proliferate the chainId * Refactor sampler to remove DeploymentConstants dependency and fixed addresses * remove duped network addresses * `asset-swapper`: enable pancake VIP route generation Co-authored-by: Jacob Evans <jacob@dekz.net> Co-authored-by: Lawrence Forman <me@merklejerk.com> * `@0x/contracts-zero-ex`: Fix `PancakeSwapFeature` sushi values (#172) * `@0x/contracts-zero-ex`: Fix `PancakeSwapFeature` sushi values * `@0x/contracts-zero-ex`: I am a bad protocologist Co-authored-by: Lawrence Forman <me@merklejerk.com> * feat: BSC Nerve + Dodo + Nerve + Ellipsis (#181) * feat: BSC Nerve + DODO v1 * CHANGELOGs * Remove extra balance fetch * Add Belt * Added Ellipsis * Update FQT address * `@0x/contracts-zero-ex`: Delete TokenSpenderFeature and get stuff compiling * `@0x/asset-swapper`: fix compilation * prettier * `@0x/asset-swapper`: Truncate LiquidityProvider source ID name * Update packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts Co-authored-by: Jacob Evans <jacob@dekz.net> * Update packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts Co-authored-by: Jacob Evans <jacob@dekz.net> * `@0x/contracts-zero-ex`: Fix BakerySwap on PackageSwapFeature (#190) * address review comments Co-authored-by: mzhu25 <mchl.zhu.96@gmail.com> Co-authored-by: Jacob Evans <jacob@dekz.net> Co-authored-by: Lawrence Forman <me@merklejerk.com>
This commit is contained in:
parent
70ddab0231
commit
164a5d44d9
@ -1,4 +1,33 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "0.21.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Encoding protocol ID and source name in bridge source ID",
|
||||||
|
"pr": 162
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Add PancakeSwapFeature",
|
||||||
|
"pr": 164
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove TokenSpender/AllowanceTarget/greedy tokens stuff",
|
||||||
|
"pr": 164
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added Nerve in BridgeAdapter",
|
||||||
|
"pr": 181
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Delete TokenSpenderFeature",
|
||||||
|
"pr": 189
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Fix PancakeSwapFeature BakerySwap swap selector",
|
||||||
|
"pr": 190
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "0.20.0",
|
"version": "0.20.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -26,6 +26,7 @@ import "./features/interfaces/ITokenSpenderFeature.sol";
|
|||||||
import "./features/interfaces/ITransformERC20Feature.sol";
|
import "./features/interfaces/ITransformERC20Feature.sol";
|
||||||
import "./features/interfaces/IMetaTransactionsFeature.sol";
|
import "./features/interfaces/IMetaTransactionsFeature.sol";
|
||||||
import "./features/interfaces/IUniswapFeature.sol";
|
import "./features/interfaces/IUniswapFeature.sol";
|
||||||
|
import "./features/interfaces/IPancakeSwapFeature.sol";
|
||||||
import "./features/interfaces/ILiquidityProviderFeature.sol";
|
import "./features/interfaces/ILiquidityProviderFeature.sol";
|
||||||
import "./features/interfaces/INativeOrdersFeature.sol";
|
import "./features/interfaces/INativeOrdersFeature.sol";
|
||||||
import "./features/interfaces/IBatchFillNativeOrdersFeature.sol";
|
import "./features/interfaces/IBatchFillNativeOrdersFeature.sol";
|
||||||
@ -36,10 +37,10 @@ import "./features/interfaces/IMultiplexFeature.sol";
|
|||||||
interface IZeroEx is
|
interface IZeroEx is
|
||||||
IOwnableFeature,
|
IOwnableFeature,
|
||||||
ISimpleFunctionRegistryFeature,
|
ISimpleFunctionRegistryFeature,
|
||||||
ITokenSpenderFeature,
|
|
||||||
ITransformERC20Feature,
|
ITransformERC20Feature,
|
||||||
IMetaTransactionsFeature,
|
IMetaTransactionsFeature,
|
||||||
IUniswapFeature,
|
IUniswapFeature,
|
||||||
|
IPancakeSwapFeature,
|
||||||
ILiquidityProviderFeature,
|
ILiquidityProviderFeature,
|
||||||
INativeOrdersFeature,
|
INativeOrdersFeature,
|
||||||
IBatchFillNativeOrdersFeature,
|
IBatchFillNativeOrdersFeature,
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
|
|
||||||
|
|
||||||
library LibSpenderRichErrors {
|
|
||||||
|
|
||||||
// solhint-disable func-name-mixedcase
|
|
||||||
|
|
||||||
function SpenderERC20TransferFromFailedError(
|
|
||||||
address token,
|
|
||||||
address owner,
|
|
||||||
address to,
|
|
||||||
uint256 amount,
|
|
||||||
bytes memory errorData
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
pure
|
|
||||||
returns (bytes memory)
|
|
||||||
{
|
|
||||||
return abi.encodeWithSelector(
|
|
||||||
bytes4(keccak256("SpenderERC20TransferFromFailedError(address,address,address,uint256,bytes)")),
|
|
||||||
token,
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
errorData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
|
||||||
import "@0x/contracts-utils/contracts/src/v06/AuthorizableV06.sol";
|
|
||||||
import "../errors/LibSpenderRichErrors.sol";
|
|
||||||
import "./IAllowanceTarget.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev The allowance target for the TokenSpender feature.
|
|
||||||
contract AllowanceTarget is
|
|
||||||
IAllowanceTarget,
|
|
||||||
AuthorizableV06
|
|
||||||
{
|
|
||||||
// solhint-disable no-unused-vars,indent,no-empty-blocks
|
|
||||||
using LibRichErrorsV06 for bytes;
|
|
||||||
|
|
||||||
/// @dev Execute an arbitrary call. Only an authority can call this.
|
|
||||||
/// @param target The call target.
|
|
||||||
/// @param callData The call data.
|
|
||||||
/// @return resultData The data returned by the call.
|
|
||||||
function executeCall(
|
|
||||||
address payable target,
|
|
||||||
bytes calldata callData
|
|
||||||
)
|
|
||||||
external
|
|
||||||
override
|
|
||||||
onlyAuthorized
|
|
||||||
returns (bytes memory resultData)
|
|
||||||
{
|
|
||||||
bool success;
|
|
||||||
(success, resultData) = target.call(callData);
|
|
||||||
if (!success) {
|
|
||||||
resultData.rrevert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/v06/interfaces/IAuthorizableV06.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev The allowance target for the TokenSpender feature.
|
|
||||||
interface IAllowanceTarget is
|
|
||||||
IAuthorizableV06
|
|
||||||
{
|
|
||||||
/// @dev Execute an arbitrary call. Only an authority can call this.
|
|
||||||
/// @param target The call target.
|
|
||||||
/// @param callData The call data.
|
|
||||||
/// @return resultData The data returned by the call.
|
|
||||||
function executeCall(
|
|
||||||
address payable target,
|
|
||||||
bytes calldata callData
|
|
||||||
)
|
|
||||||
external
|
|
||||||
returns (bytes memory resultData);
|
|
||||||
}
|
|
@ -47,15 +47,14 @@ contract LiquidityProviderFeature is
|
|||||||
/// @dev Name of this feature.
|
/// @dev Name of this feature.
|
||||||
string public constant override FEATURE_NAME = "LiquidityProviderFeature";
|
string public constant override FEATURE_NAME = "LiquidityProviderFeature";
|
||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 3);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 4);
|
||||||
|
|
||||||
/// @dev The sandbox contract address.
|
/// @dev The sandbox contract address.
|
||||||
ILiquidityProviderSandbox public immutable sandbox;
|
ILiquidityProviderSandbox public immutable sandbox;
|
||||||
|
|
||||||
constructor(LiquidityProviderSandbox sandbox_, bytes32 greedyTokensBloomFilter)
|
constructor(LiquidityProviderSandbox sandbox_)
|
||||||
public
|
public
|
||||||
FixinCommon()
|
FixinCommon()
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{
|
{
|
||||||
sandbox = sandbox_;
|
sandbox = sandbox_;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ contract MetaTransactionsFeature is
|
|||||||
/// @dev Name of this feature.
|
/// @dev Name of this feature.
|
||||||
string public constant override FEATURE_NAME = "MetaTransactions";
|
string public constant override FEATURE_NAME = "MetaTransactions";
|
||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1);
|
||||||
/// @dev EIP712 typehash of the `MetaTransactionData` struct.
|
/// @dev EIP712 typehash of the `MetaTransactionData` struct.
|
||||||
bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256(
|
bytes32 public immutable MTX_EIP712_TYPEHASH = keccak256(
|
||||||
"MetaTransactionData("
|
"MetaTransactionData("
|
||||||
@ -105,11 +105,10 @@ contract MetaTransactionsFeature is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(address zeroExAddress, bytes32 greedyTokensBloomFilter)
|
constructor(address zeroExAddress)
|
||||||
public
|
public
|
||||||
FixinCommon()
|
FixinCommon()
|
||||||
FixinEIP712(zeroExAddress)
|
FixinEIP712(zeroExAddress)
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{
|
{
|
||||||
// solhint-disable-next-line no-empty-blocks
|
// solhint-disable-next-line no-empty-blocks
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ contract MultiplexFeature is
|
|||||||
/// @dev Name of this feature.
|
/// @dev Name of this feature.
|
||||||
string public constant override FEATURE_NAME = "MultiplexFeature";
|
string public constant override FEATURE_NAME = "MultiplexFeature";
|
||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
|
||||||
|
|
||||||
/// @dev The WETH token contract.
|
/// @dev The WETH token contract.
|
||||||
IEtherTokenV06 private immutable weth;
|
IEtherTokenV06 private immutable weth;
|
||||||
@ -73,12 +73,10 @@ contract MultiplexFeature is
|
|||||||
constructor(
|
constructor(
|
||||||
address zeroExAddress,
|
address zeroExAddress,
|
||||||
IEtherTokenV06 weth_,
|
IEtherTokenV06 weth_,
|
||||||
ILiquidityProviderSandbox sandbox_,
|
ILiquidityProviderSandbox sandbox_
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
FixinEIP712(zeroExAddress)
|
FixinEIP712(zeroExAddress)
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{
|
{
|
||||||
weth = weth_;
|
weth = weth_;
|
||||||
sandbox = sandbox_;
|
sandbox = sandbox_;
|
||||||
|
@ -34,15 +34,14 @@ contract NativeOrdersFeature is
|
|||||||
/// @dev Name of this feature.
|
/// @dev Name of this feature.
|
||||||
string public constant override FEATURE_NAME = "LimitOrders";
|
string public constant override FEATURE_NAME = "LimitOrders";
|
||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address zeroExAddress,
|
address zeroExAddress,
|
||||||
IEtherTokenV06 weth,
|
IEtherTokenV06 weth,
|
||||||
IStaking staking,
|
IStaking staking,
|
||||||
FeeCollectorController feeCollectorController,
|
FeeCollectorController feeCollectorController,
|
||||||
uint32 protocolFeeMultiplier,
|
uint32 protocolFeeMultiplier
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
NativeOrdersSettlement(
|
NativeOrdersSettlement(
|
||||||
@ -50,8 +49,7 @@ contract NativeOrdersFeature is
|
|||||||
weth,
|
weth,
|
||||||
staking,
|
staking,
|
||||||
feeCollectorController,
|
feeCollectorController,
|
||||||
protocolFeeMultiplier,
|
protocolFeeMultiplier
|
||||||
greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
|
423
contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol
Normal file
423
contracts/zero-ex/contracts/src/features/PancakeSwapFeature.sol
Normal file
@ -0,0 +1,423 @@
|
|||||||
|
// 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/IERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||||
|
import "../migrations/LibMigrate.sol";
|
||||||
|
import "../fixins/FixinCommon.sol";
|
||||||
|
import "./interfaces/IFeature.sol";
|
||||||
|
import "./interfaces/IPancakeSwapFeature.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev VIP pancake fill functions.
|
||||||
|
contract PancakeSwapFeature is
|
||||||
|
IFeature,
|
||||||
|
IPancakeSwapFeature,
|
||||||
|
FixinCommon
|
||||||
|
{
|
||||||
|
/// @dev Name of this feature.
|
||||||
|
string public constant override FEATURE_NAME = "PancakeSwapFeature";
|
||||||
|
/// @dev Version of this feature.
|
||||||
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 1);
|
||||||
|
/// @dev WBNB contract.
|
||||||
|
IEtherTokenV06 private immutable WBNB;
|
||||||
|
|
||||||
|
// 0xFF + address of the PancakeSwap factory contract.
|
||||||
|
uint256 constant private FF_PANCAKESWAP_FACTORY = 0xffbcfccbde45ce874adcb698cc183debcf179528120000000000000000000000;
|
||||||
|
// 0xFF + address of the BakerySwap factory contract.
|
||||||
|
uint256 constant private FF_BAKERYSWAP_FACTORY = 0xff01bf7c66c6bd861915cdaae475042d3c4bae16a70000000000000000000000;
|
||||||
|
// 0xFF + address of the SushiSwap factory contract.
|
||||||
|
uint256 constant private FF_SUSHISWAP_FACTORY = 0xffc35DADB65012eC5796536bD9864eD8773aBc74C40000000000000000000000;
|
||||||
|
// Init code hash of the PancakeSwap pair contract.
|
||||||
|
uint256 constant private PANCAKESWAP_PAIR_INIT_CODE_HASH = 0xd0d4c4cd0848c93cb4fd1f498d7013ee6bfb25783ea21593d5834f5d250ece66;
|
||||||
|
// Init code hash of the BakerySwap pair contract.
|
||||||
|
uint256 constant private BAKERYSWAP_PAIR_INIT_CODE_HASH = 0xe2e87433120e32c4738a7d8f3271f3d872cbe16241d67537139158d90bac61d3;
|
||||||
|
// Init code hash of the SushiSwap pair contract.
|
||||||
|
uint256 constant private SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303;
|
||||||
|
// Mask of the lower 20 bytes of a bytes32.
|
||||||
|
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
|
||||||
|
// BNB pseudo-token address.
|
||||||
|
uint256 constant private ETH_TOKEN_ADDRESS_32 = 0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
|
||||||
|
// Maximum token quantity that can be swapped against the PancakeSwapPair contract.
|
||||||
|
uint256 constant private MAX_SWAP_AMOUNT = 2**112;
|
||||||
|
|
||||||
|
// bytes4(keccak256("executeCall(address,bytes)"))
|
||||||
|
uint256 constant private ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32 = 0xbca8c7b500000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("getReserves()"))
|
||||||
|
uint256 constant private PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32 = 0x0902f1ac00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("swap(uint256,uint256,address,bytes)"))
|
||||||
|
uint256 constant private PANCAKESWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x022c0d9f00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("swap(uint256,uint256,address)"))
|
||||||
|
uint256 constant private BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32 = 0x6d9a640a00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("transferFrom(address,address,uint256)"))
|
||||||
|
uint256 constant private TRANSFER_FROM_CALL_SELECTOR_32 = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("allowance(address,address)"))
|
||||||
|
uint256 constant private ALLOWANCE_CALL_SELECTOR_32 = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("withdraw(uint256)"))
|
||||||
|
uint256 constant private WETH_WITHDRAW_CALL_SELECTOR_32 = 0x2e1a7d4d00000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("deposit()"))
|
||||||
|
uint256 constant private WETH_DEPOSIT_CALL_SELECTOR_32 = 0xd0e30db000000000000000000000000000000000000000000000000000000000;
|
||||||
|
// bytes4(keccak256("transfer(address,uint256)"))
|
||||||
|
uint256 constant private ERC20_TRANSFER_CALL_SELECTOR_32 = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;
|
||||||
|
|
||||||
|
/// @dev Construct this contract.
|
||||||
|
/// @param wbnb The WBNB contract.
|
||||||
|
constructor(IEtherTokenV06 wbnb) public {
|
||||||
|
WBNB = wbnb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Initialize and register this feature.
|
||||||
|
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||||
|
/// @return success `LibMigrate.SUCCESS` on success.
|
||||||
|
function migrate()
|
||||||
|
external
|
||||||
|
returns (bytes4 success)
|
||||||
|
{
|
||||||
|
_registerFeatureFunction(this.sellToPancakeSwap.selector);
|
||||||
|
return LibMigrate.MIGRATE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Efficiently sell directly to pancake/BakerySwap/SushiSwap.
|
||||||
|
/// @param tokens Sell path.
|
||||||
|
/// @param sellAmount of `tokens[0]` Amount to sell.
|
||||||
|
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
|
||||||
|
/// @param fork The protocol fork to use.
|
||||||
|
/// @return buyAmount Amount of `tokens[-1]` bought.
|
||||||
|
function sellToPancakeSwap(
|
||||||
|
IERC20TokenV06[] calldata tokens,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount,
|
||||||
|
ProtocolFork fork
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
override
|
||||||
|
returns (uint256 buyAmount)
|
||||||
|
{
|
||||||
|
require(tokens.length > 1, "PancakeSwapFeature/InvalidTokensLength");
|
||||||
|
{
|
||||||
|
// Load immutables onto the stack.
|
||||||
|
IEtherTokenV06 wbnb = WBNB;
|
||||||
|
|
||||||
|
// Store some vars in memory to get around stack limits.
|
||||||
|
assembly {
|
||||||
|
// calldataload(mload(0xA00)) == first element of `tokens` array
|
||||||
|
mstore(0xA00, add(calldataload(0x04), 0x24))
|
||||||
|
// mload(0xA20) == fork
|
||||||
|
mstore(0xA20, fork)
|
||||||
|
// mload(0xA40) == WBNB
|
||||||
|
mstore(0xA40, wbnb)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
// numPairs == tokens.length - 1
|
||||||
|
let numPairs := sub(calldataload(add(calldataload(0x04), 0x4)), 1)
|
||||||
|
// We use the previous buy amount as the sell amount for the next
|
||||||
|
// pair in a path. So for the first swap we want to set it to `sellAmount`.
|
||||||
|
buyAmount := sellAmount
|
||||||
|
let buyToken
|
||||||
|
let nextPair := 0
|
||||||
|
|
||||||
|
for {let i := 0} lt(i, numPairs) {i := add(i, 1)} {
|
||||||
|
// sellToken = tokens[i]
|
||||||
|
let sellToken := loadTokenAddress(i)
|
||||||
|
// buyToken = tokens[i+1]
|
||||||
|
buyToken := loadTokenAddress(add(i, 1))
|
||||||
|
// The canonical ordering of this token pair.
|
||||||
|
let pairOrder := lt(normalizeToken(sellToken), normalizeToken(buyToken))
|
||||||
|
|
||||||
|
// Compute the pair address if it hasn't already been computed
|
||||||
|
// from the last iteration.
|
||||||
|
let pair := nextPair
|
||||||
|
if iszero(pair) {
|
||||||
|
pair := computePairAddress(sellToken, buyToken)
|
||||||
|
nextPair := 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if iszero(i) {
|
||||||
|
// This is the first token in the path.
|
||||||
|
switch eq(sellToken, ETH_TOKEN_ADDRESS_32)
|
||||||
|
case 0 { // Not selling BNB. Selling an ERC20 instead.
|
||||||
|
// Make sure BNB was not attached to the call.
|
||||||
|
if gt(callvalue(), 0) {
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
// For the first pair we need to transfer sellTokens into the
|
||||||
|
// pair contract.
|
||||||
|
moveTakerTokensTo(sellToken, pair, sellAmount)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
// If selling BNB, we need to wrap it to WBNB and transfer to the
|
||||||
|
// pair contract.
|
||||||
|
if iszero(eq(callvalue(), sellAmount)) {
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
sellToken := mload(0xA40)// Re-assign to WBNB
|
||||||
|
// Call `WBNB.deposit{value: sellAmount}()`
|
||||||
|
mstore(0xB00, WETH_DEPOSIT_CALL_SELECTOR_32)
|
||||||
|
if iszero(call(gas(), sellToken, sellAmount, 0xB00, 0x4, 0x00, 0x0)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
// Call `WBNB.transfer(pair, sellAmount)`
|
||||||
|
mstore(0xB00, ERC20_TRANSFER_CALL_SELECTOR_32)
|
||||||
|
mstore(0xB04, pair)
|
||||||
|
mstore(0xB24, sellAmount)
|
||||||
|
if iszero(call(gas(), sellToken, 0, 0xB00, 0x44, 0x00, 0x0)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No need to check results, if deposit/transfers failed the PancakeSwapPair will
|
||||||
|
// reject our trade (or it may succeed if somehow the reserve was out of sync)
|
||||||
|
// this is fine for the taker.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call pair.getReserves(), store the results at `0xC00`
|
||||||
|
mstore(0xB00, PANCAKESWAP_PAIR_RESERVES_CALL_SELECTOR_32)
|
||||||
|
if iszero(staticcall(gas(), pair, 0xB00, 0x4, 0xC00, 0x40)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
// Revert if the pair contract does not return at least two words.
|
||||||
|
if lt(returndatasize(), 0x40) {
|
||||||
|
mstore(0, pair)
|
||||||
|
revert(0, 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sell amount for this hop is the previous buy amount.
|
||||||
|
let pairSellAmount := buyAmount
|
||||||
|
// Compute the buy amount based on the pair reserves.
|
||||||
|
{
|
||||||
|
let sellReserve
|
||||||
|
let buyReserve
|
||||||
|
switch iszero(pairOrder)
|
||||||
|
case 0 {
|
||||||
|
// Transpose if pair order is different.
|
||||||
|
sellReserve := mload(0xC00)
|
||||||
|
buyReserve := mload(0xC20)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
sellReserve := mload(0xC20)
|
||||||
|
buyReserve := mload(0xC00)
|
||||||
|
}
|
||||||
|
// Ensure that the sellAmount is < 2¹¹².
|
||||||
|
if gt(pairSellAmount, MAX_SWAP_AMOUNT) {
|
||||||
|
revert(0, 0)
|
||||||
|
}
|
||||||
|
// Pairs are in the range (0, 2¹¹²) so this shouldn't overflow.
|
||||||
|
// buyAmount = (pairSellAmount * 997 * buyReserve) /
|
||||||
|
// (pairSellAmount * 997 + sellReserve * 1000);
|
||||||
|
let sellAmountWithFee := mul(pairSellAmount, 997)
|
||||||
|
buyAmount := div(
|
||||||
|
mul(sellAmountWithFee, buyReserve),
|
||||||
|
add(sellAmountWithFee, mul(sellReserve, 1000))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let receiver
|
||||||
|
// Is this the last pair contract?
|
||||||
|
switch eq(add(i, 1), numPairs)
|
||||||
|
case 0 {
|
||||||
|
// Not the last pair contract, so forward bought tokens to
|
||||||
|
// the next pair contract.
|
||||||
|
nextPair := computePairAddress(
|
||||||
|
buyToken,
|
||||||
|
loadTokenAddress(add(i, 2))
|
||||||
|
)
|
||||||
|
receiver := nextPair
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
// The last pair contract.
|
||||||
|
// Forward directly to taker UNLESS they want BNB back.
|
||||||
|
switch eq(buyToken, ETH_TOKEN_ADDRESS_32)
|
||||||
|
case 0 {
|
||||||
|
receiver := caller()
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
receiver := address()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call pair.swap()
|
||||||
|
switch mload(0xA20) // fork
|
||||||
|
case 1 {
|
||||||
|
mstore(0xB00, BAKERYSWAP_PAIR_SWAP_CALL_SELECTOR_32)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
mstore(0xB00, PANCAKESWAP_PAIR_SWAP_CALL_SELECTOR_32)
|
||||||
|
}
|
||||||
|
switch pairOrder
|
||||||
|
case 0 {
|
||||||
|
mstore(0xB04, buyAmount)
|
||||||
|
mstore(0xB24, 0)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
mstore(0xB04, 0)
|
||||||
|
mstore(0xB24, buyAmount)
|
||||||
|
}
|
||||||
|
mstore(0xB44, receiver)
|
||||||
|
mstore(0xB64, 0x80)
|
||||||
|
mstore(0xB84, 0)
|
||||||
|
if iszero(call(gas(), pair, 0, 0xB00, 0xA4, 0, 0)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
} // End for-loop.
|
||||||
|
|
||||||
|
// If buying BNB, unwrap the WBNB first
|
||||||
|
if eq(buyToken, ETH_TOKEN_ADDRESS_32) {
|
||||||
|
// Call `WBNB.withdraw(buyAmount)`
|
||||||
|
mstore(0xB00, WETH_WITHDRAW_CALL_SELECTOR_32)
|
||||||
|
mstore(0xB04, buyAmount)
|
||||||
|
if iszero(call(gas(), mload(0xA40), 0, 0xB00, 0x24, 0x00, 0x0)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
// Transfer BNB to the caller.
|
||||||
|
if iszero(call(gas(), caller(), buyAmount, 0xB00, 0x0, 0x00, 0x0)) {
|
||||||
|
bubbleRevert()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Functions ///////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Load a token address from the `tokens` calldata argument.
|
||||||
|
function loadTokenAddress(idx) -> addr {
|
||||||
|
addr := and(ADDRESS_MASK, calldataload(add(mload(0xA00), mul(idx, 0x20))))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert BNB pseudo-token addresses to WBNB.
|
||||||
|
function normalizeToken(token) -> normalized {
|
||||||
|
normalized := token
|
||||||
|
// Translate BNB pseudo-tokens to WBNB.
|
||||||
|
if eq(token, ETH_TOKEN_ADDRESS_32) {
|
||||||
|
normalized := mload(0xA40)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the address of the PancakeSwapPair contract given two
|
||||||
|
// tokens.
|
||||||
|
function computePairAddress(tokenA, tokenB) -> pair {
|
||||||
|
// Convert BNB pseudo-token addresses to WBNB.
|
||||||
|
tokenA := normalizeToken(tokenA)
|
||||||
|
tokenB := normalizeToken(tokenB)
|
||||||
|
// There is one contract for every combination of tokens,
|
||||||
|
// which is deployed using CREATE2.
|
||||||
|
// The derivation of this address is given by:
|
||||||
|
// address(keccak256(abi.encodePacked(
|
||||||
|
// bytes(0xFF),
|
||||||
|
// address(PANCAKESWAP_FACTORY_ADDRESS),
|
||||||
|
// keccak256(abi.encodePacked(
|
||||||
|
// tokenA < tokenB ? tokenA : tokenB,
|
||||||
|
// tokenA < tokenB ? tokenB : tokenA,
|
||||||
|
// )),
|
||||||
|
// bytes32(PANCAKESWAP_PAIR_INIT_CODE_HASH),
|
||||||
|
// )));
|
||||||
|
|
||||||
|
// Compute the salt (the hash of the sorted tokens).
|
||||||
|
// Tokens are written in reverse memory order to packed encode
|
||||||
|
// them as two 20-byte values in a 40-byte chunk of memory
|
||||||
|
// starting at 0xB0C.
|
||||||
|
switch lt(tokenA, tokenB)
|
||||||
|
case 0 {
|
||||||
|
mstore(0xB14, tokenA)
|
||||||
|
mstore(0xB00, tokenB)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
mstore(0xB14, tokenB)
|
||||||
|
mstore(0xB00, tokenA)
|
||||||
|
}
|
||||||
|
let salt := keccak256(0xB0C, 0x28)
|
||||||
|
// Compute the pair address by hashing all the components together.
|
||||||
|
switch mload(0xA20) // fork
|
||||||
|
case 0 {
|
||||||
|
mstore(0xB00, FF_PANCAKESWAP_FACTORY)
|
||||||
|
mstore(0xB15, salt)
|
||||||
|
mstore(0xB35, PANCAKESWAP_PAIR_INIT_CODE_HASH)
|
||||||
|
}
|
||||||
|
case 1 {
|
||||||
|
mstore(0xB00, FF_BAKERYSWAP_FACTORY)
|
||||||
|
mstore(0xB15, salt)
|
||||||
|
mstore(0xB35, BAKERYSWAP_PAIR_INIT_CODE_HASH)
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
mstore(0xB00, FF_SUSHISWAP_FACTORY)
|
||||||
|
mstore(0xB15, salt)
|
||||||
|
mstore(0xB35, SUSHISWAP_PAIR_INIT_CODE_HASH)
|
||||||
|
}
|
||||||
|
pair := and(ADDRESS_MASK, keccak256(0xB00, 0x55))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert with the return data from the most recent call.
|
||||||
|
function bubbleRevert() {
|
||||||
|
returndatacopy(0, 0, returndatasize())
|
||||||
|
revert(0, returndatasize())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move `amount` tokens from the taker/caller to `to`.
|
||||||
|
function moveTakerTokensTo(token, to, amount) {
|
||||||
|
// Perform a `transferFrom()`
|
||||||
|
mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
|
||||||
|
mstore(0xB04, caller())
|
||||||
|
mstore(0xB24, to)
|
||||||
|
mstore(0xB44, amount)
|
||||||
|
|
||||||
|
let success := call(
|
||||||
|
gas(),
|
||||||
|
token,
|
||||||
|
0,
|
||||||
|
0xB00,
|
||||||
|
0x64,
|
||||||
|
0xC00,
|
||||||
|
// Copy only the first 32 bytes of return data. We
|
||||||
|
// only care about reading a boolean in the success
|
||||||
|
// case. We will use returndatacopy() in the failure case.
|
||||||
|
0x20
|
||||||
|
)
|
||||||
|
|
||||||
|
let rdsize := returndatasize()
|
||||||
|
|
||||||
|
// Check for ERC20 success. ERC20 tokens should
|
||||||
|
// return a boolean, but some return nothing or
|
||||||
|
// extra data. We accept 0-length return data as
|
||||||
|
// success, or at least 32 bytes that starts with
|
||||||
|
// a 32-byte boolean true.
|
||||||
|
success := and(
|
||||||
|
success, // call itself succeeded
|
||||||
|
or(
|
||||||
|
iszero(rdsize), // no return data, or
|
||||||
|
and(
|
||||||
|
iszero(lt(rdsize, 32)), // at least 32 bytes
|
||||||
|
eq(mload(0xC00), 1) // starts with uint256(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if iszero(success) {
|
||||||
|
// Revert with the data returned from the transferFrom call.
|
||||||
|
returndatacopy(0, 0, rdsize)
|
||||||
|
revert(0, rdsize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revert if we bought too little.
|
||||||
|
require(buyAmount >= minBuyAmount, "PancakeSwapFeature/UnderBought");
|
||||||
|
}
|
||||||
|
}
|
@ -1,137 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
|
||||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
|
||||||
import "../errors/LibSpenderRichErrors.sol";
|
|
||||||
import "../fixins/FixinCommon.sol";
|
|
||||||
import "../migrations/LibMigrate.sol";
|
|
||||||
import "../external/IAllowanceTarget.sol";
|
|
||||||
import "../storage/LibTokenSpenderStorage.sol";
|
|
||||||
import "./interfaces/IFeature.sol";
|
|
||||||
import "./interfaces/ITokenSpenderFeature.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev Feature that allows spending token allowances.
|
|
||||||
contract TokenSpenderFeature is
|
|
||||||
IFeature,
|
|
||||||
ITokenSpenderFeature,
|
|
||||||
FixinCommon
|
|
||||||
{
|
|
||||||
// solhint-disable
|
|
||||||
/// @dev Name of this feature.
|
|
||||||
string public constant override FEATURE_NAME = "TokenSpender";
|
|
||||||
/// @dev Version of this feature.
|
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
|
|
||||||
// solhint-enable
|
|
||||||
|
|
||||||
using LibRichErrorsV06 for bytes;
|
|
||||||
|
|
||||||
/// @dev Initialize and register this feature. Should be delegatecalled
|
|
||||||
/// into during a `Migrate.migrate()`.
|
|
||||||
/// @param allowanceTarget An `allowanceTarget` instance, configured to have
|
|
||||||
/// the ZeroeEx contract as an authority.
|
|
||||||
/// @return success `MIGRATE_SUCCESS` on success.
|
|
||||||
function migrate(IAllowanceTarget allowanceTarget)
|
|
||||||
external
|
|
||||||
returns (bytes4 success)
|
|
||||||
{
|
|
||||||
LibTokenSpenderStorage.getStorage().allowanceTarget = allowanceTarget;
|
|
||||||
_registerFeatureFunction(this.getAllowanceTarget.selector);
|
|
||||||
_registerFeatureFunction(this._spendERC20Tokens.selector);
|
|
||||||
_registerFeatureFunction(this.getSpendableERC20BalanceOf.selector);
|
|
||||||
return LibMigrate.MIGRATE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Transfers ERC20 tokens from `owner` to `to`. Only callable from within.
|
|
||||||
/// @param token The token to spend.
|
|
||||||
/// @param owner The owner of the tokens.
|
|
||||||
/// @param to The recipient of the tokens.
|
|
||||||
/// @param amount The amount of `token` to transfer.
|
|
||||||
function _spendERC20Tokens(
|
|
||||||
IERC20TokenV06 token,
|
|
||||||
address owner,
|
|
||||||
address to,
|
|
||||||
uint256 amount
|
|
||||||
)
|
|
||||||
external
|
|
||||||
override
|
|
||||||
onlySelf
|
|
||||||
{
|
|
||||||
IAllowanceTarget spender = LibTokenSpenderStorage.getStorage().allowanceTarget;
|
|
||||||
// Have the allowance target execute an ERC20 `transferFrom()`.
|
|
||||||
(bool didSucceed, bytes memory resultData) = address(spender).call(
|
|
||||||
abi.encodeWithSelector(
|
|
||||||
IAllowanceTarget.executeCall.selector,
|
|
||||||
address(token),
|
|
||||||
abi.encodeWithSelector(
|
|
||||||
IERC20TokenV06.transferFrom.selector,
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (didSucceed) {
|
|
||||||
resultData = abi.decode(resultData, (bytes));
|
|
||||||
}
|
|
||||||
if (!didSucceed || !LibERC20TokenV06.isSuccessfulResult(resultData)) {
|
|
||||||
LibSpenderRichErrors.SpenderERC20TransferFromFailedError(
|
|
||||||
address(token),
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
resultData
|
|
||||||
).rrevert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
|
|
||||||
/// pulled from `owner` by the token spender.
|
|
||||||
/// @param token The token to spend.
|
|
||||||
/// @param owner The owner of the tokens.
|
|
||||||
/// @return amount The amount of tokens that can be pulled.
|
|
||||||
function getSpendableERC20BalanceOf(IERC20TokenV06 token, address owner)
|
|
||||||
external
|
|
||||||
override
|
|
||||||
view
|
|
||||||
returns (uint256 amount)
|
|
||||||
{
|
|
||||||
return LibSafeMathV06.min256(
|
|
||||||
token.allowance(owner, address(LibTokenSpenderStorage.getStorage().allowanceTarget)),
|
|
||||||
token.balanceOf(owner)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Get the address of the allowance target.
|
|
||||||
/// @return target The target of token allowances.
|
|
||||||
function getAllowanceTarget()
|
|
||||||
external
|
|
||||||
override
|
|
||||||
view
|
|
||||||
returns (address target)
|
|
||||||
{
|
|
||||||
return address(LibTokenSpenderStorage.getStorage().allowanceTarget);
|
|
||||||
}
|
|
||||||
}
|
|
@ -60,10 +60,7 @@ contract TransformERC20Feature is
|
|||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 3, 1);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 3, 1);
|
||||||
|
|
||||||
constructor(bytes32 greedyTokensBloomFilter)
|
constructor() public {}
|
||||||
public
|
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/// @dev Initialize and register this feature.
|
/// @dev Initialize and register this feature.
|
||||||
/// Should be delegatecalled by `Migrate.migrate()`.
|
/// Should be delegatecalled by `Migrate.migrate()`.
|
||||||
|
@ -23,7 +23,6 @@ pragma experimental ABIEncoderV2;
|
|||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||||
import "../migrations/LibMigrate.sol";
|
import "../migrations/LibMigrate.sol";
|
||||||
import "../external/IAllowanceTarget.sol";
|
|
||||||
import "../fixins/FixinCommon.sol";
|
import "../fixins/FixinCommon.sol";
|
||||||
import "./interfaces/IFeature.sol";
|
import "./interfaces/IFeature.sol";
|
||||||
import "./interfaces/IUniswapFeature.sol";
|
import "./interfaces/IUniswapFeature.sol";
|
||||||
@ -38,13 +37,9 @@ contract UniswapFeature is
|
|||||||
/// @dev Name of this feature.
|
/// @dev Name of this feature.
|
||||||
string public constant override FEATURE_NAME = "UniswapFeature";
|
string public constant override FEATURE_NAME = "UniswapFeature";
|
||||||
/// @dev Version of this feature.
|
/// @dev Version of this feature.
|
||||||
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 1);
|
uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 2);
|
||||||
/// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
|
|
||||||
bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
|
|
||||||
/// @dev WETH contract.
|
/// @dev WETH contract.
|
||||||
IEtherTokenV06 private immutable WETH;
|
IEtherTokenV06 private immutable WETH;
|
||||||
/// @dev AllowanceTarget instance.
|
|
||||||
IAllowanceTarget private immutable ALLOWANCE_TARGET;
|
|
||||||
|
|
||||||
// 0xFF + address of the UniswapV2Factory contract.
|
// 0xFF + address of the UniswapV2Factory contract.
|
||||||
uint256 constant private FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000;
|
uint256 constant private FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000;
|
||||||
@ -80,16 +75,8 @@ contract UniswapFeature is
|
|||||||
|
|
||||||
/// @dev Construct this contract.
|
/// @dev Construct this contract.
|
||||||
/// @param weth The WETH contract.
|
/// @param weth The WETH contract.
|
||||||
/// @param allowanceTarget The AllowanceTarget contract.
|
constructor(IEtherTokenV06 weth) public {
|
||||||
/// @param greedyTokensBloomFilter The bloom filter for greedy tokens.
|
|
||||||
constructor(
|
|
||||||
IEtherTokenV06 weth,
|
|
||||||
IAllowanceTarget allowanceTarget,
|
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
) public {
|
|
||||||
WETH = weth;
|
WETH = weth;
|
||||||
ALLOWANCE_TARGET = allowanceTarget;
|
|
||||||
GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Initialize and register this feature.
|
/// @dev Initialize and register this feature.
|
||||||
@ -124,8 +111,6 @@ contract UniswapFeature is
|
|||||||
{
|
{
|
||||||
// Load immutables onto the stack.
|
// Load immutables onto the stack.
|
||||||
IEtherTokenV06 weth = WETH;
|
IEtherTokenV06 weth = WETH;
|
||||||
IAllowanceTarget allowanceTarget = ALLOWANCE_TARGET;
|
|
||||||
bytes32 greedyTokensBloomFilter = GREEDY_TOKENS_BLOOM_FILTER;
|
|
||||||
|
|
||||||
// Store some vars in memory to get around stack limits.
|
// Store some vars in memory to get around stack limits.
|
||||||
assembly {
|
assembly {
|
||||||
@ -135,10 +120,6 @@ contract UniswapFeature is
|
|||||||
mstore(0xA20, isSushi)
|
mstore(0xA20, isSushi)
|
||||||
// mload(0xA40) == WETH
|
// mload(0xA40) == WETH
|
||||||
mstore(0xA40, weth)
|
mstore(0xA40, weth)
|
||||||
// mload(0xA60) == ALLOWANCE_TARGET
|
|
||||||
mstore(0xA60, allowanceTarget)
|
|
||||||
// mload(0xA80) == GREEDY_TOKENS_BLOOM_FILTER
|
|
||||||
mstore(0xA80, greedyTokensBloomFilter)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,38 +354,7 @@ contract UniswapFeature is
|
|||||||
|
|
||||||
// Move `amount` tokens from the taker/caller to `to`.
|
// Move `amount` tokens from the taker/caller to `to`.
|
||||||
function moveTakerTokensTo(token, to, amount) {
|
function moveTakerTokensTo(token, to, amount) {
|
||||||
|
// Perform a `transferFrom()`
|
||||||
// If the token is possibly greedy, we check the allowance rather
|
|
||||||
// than relying on letting the transferFrom() call fail and
|
|
||||||
// falling through to legacy allowance target because the token
|
|
||||||
// will eat all our gas.
|
|
||||||
if isTokenPossiblyGreedy(token) {
|
|
||||||
// Check if we have enough direct allowance by calling
|
|
||||||
// `token.allowance()`
|
|
||||||
mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32)
|
|
||||||
mstore(0xB04, caller())
|
|
||||||
mstore(0xB24, address())
|
|
||||||
let success := staticcall(gas(), token, 0xB00, 0x44, 0xC00, 0x20)
|
|
||||||
if iszero(success) {
|
|
||||||
// Call to allowance() failed.
|
|
||||||
bubbleRevert()
|
|
||||||
}
|
|
||||||
// Make sure the allowance call returned at least a word.
|
|
||||||
if lt(returndatasize(), 0x20) {
|
|
||||||
revert(0, 0)
|
|
||||||
}
|
|
||||||
// Call succeeded.
|
|
||||||
// Result is stored in 0xC00-0xC20.
|
|
||||||
if lt(mload(0xC00), amount) {
|
|
||||||
// We don't have enough direct allowance, so try
|
|
||||||
// going through the legacy allowance taregt.
|
|
||||||
moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
|
|
||||||
leave
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise we will optimistically try to perform a `transferFrom()`
|
|
||||||
// directly then if it fails we will go through the legacy allowance target.
|
|
||||||
mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
|
mstore(0xB00, TRANSFER_FROM_CALL_SELECTOR_32)
|
||||||
mstore(0xB04, caller())
|
mstore(0xB04, caller())
|
||||||
mstore(0xB24, to)
|
mstore(0xB24, to)
|
||||||
@ -419,8 +369,7 @@ contract UniswapFeature is
|
|||||||
0xC00,
|
0xC00,
|
||||||
// Copy only the first 32 bytes of return data. We
|
// Copy only the first 32 bytes of return data. We
|
||||||
// only care about reading a boolean in the success
|
// only care about reading a boolean in the success
|
||||||
// case, and we discard the return data in the
|
// case. We will use returndatacopy() in the failure case.
|
||||||
// failure case.
|
|
||||||
0x20
|
0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -443,37 +392,11 @@ contract UniswapFeature is
|
|||||||
)
|
)
|
||||||
|
|
||||||
if iszero(success) {
|
if iszero(success) {
|
||||||
// Try to fall back to the allowance target.
|
// Revert with the data returned from the transferFrom call.
|
||||||
moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount)
|
returndatacopy(0, 0, rdsize)
|
||||||
|
revert(0, rdsize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move tokens by going through the legacy allowance target contract.
|
|
||||||
function moveTakerTokensToWithLegacyAllowanceTarget(token, to, amount) {
|
|
||||||
mstore(0xB00, ALLOWANCE_TARGET_EXECUTE_CALL_SELECTOR_32)
|
|
||||||
mstore(0xB04, token)
|
|
||||||
mstore(0xB24, 0x40)
|
|
||||||
mstore(0xB44, 0x64)
|
|
||||||
mstore(0xB64, TRANSFER_FROM_CALL_SELECTOR_32)
|
|
||||||
mstore(0xB68, caller())
|
|
||||||
mstore(0xB88, to)
|
|
||||||
mstore(0xBA8, amount)
|
|
||||||
if iszero(call(gas(), mload(0xA60), 0, 0xB00, 0xC8, 0x00, 0x0)) {
|
|
||||||
bubbleRevert()
|
|
||||||
}
|
|
||||||
// If this fall back failed, the swap will most likely fail
|
|
||||||
// so there's no need to validate the result.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks if a token possibly belongs to the GREEDY_TOKENS_BLOOM_FILTER
|
|
||||||
// bloom filter.
|
|
||||||
function isTokenPossiblyGreedy(token) -> isPossiblyGreedy {
|
|
||||||
// The hash is given by:
|
|
||||||
// (1 << (keccak256(token) % 256)) | (1 << (token % 256))
|
|
||||||
mstore(0, token)
|
|
||||||
let h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1))
|
|
||||||
isPossiblyGreedy := eq(and(h, mload(0xA80)), h)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Revert if we bought too little.
|
// Revert if we bought too little.
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
// 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/IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
/// @dev VIP PancakeSwap/BakerySwap/SushiSwap fill functions.
|
||||||
|
interface IPancakeSwapFeature {
|
||||||
|
|
||||||
|
enum ProtocolFork {
|
||||||
|
PancakeSwap,
|
||||||
|
BakerySwap,
|
||||||
|
SushiSwap
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap.
|
||||||
|
/// @param tokens Sell path.
|
||||||
|
/// @param sellAmount of `tokens[0]` Amount to sell.
|
||||||
|
/// @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
|
||||||
|
/// @param fork The protocol fork to use.
|
||||||
|
/// @return buyAmount Amount of `tokens[-1]` bought.
|
||||||
|
function sellToPancakeSwap(
|
||||||
|
IERC20TokenV06[] calldata tokens,
|
||||||
|
uint256 sellAmount,
|
||||||
|
uint256 minBuyAmount,
|
||||||
|
ProtocolFork fork
|
||||||
|
)
|
||||||
|
external
|
||||||
|
payable
|
||||||
|
returns (uint256 buyAmount);
|
||||||
|
}
|
@ -40,11 +40,10 @@ abstract contract NativeOrdersCancellation is
|
|||||||
uint256 private constant HIGH_BIT = 1 << 255;
|
uint256 private constant HIGH_BIT = 1 << 255;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address zeroExAddress,
|
address zeroExAddress
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
NativeOrdersInfo(zeroExAddress, greedyTokensBloomFilter)
|
NativeOrdersInfo(zeroExAddress)
|
||||||
{
|
{
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,10 @@ abstract contract NativeOrdersInfo is
|
|||||||
uint256 private constant HIGH_BIT = 1 << 255;
|
uint256 private constant HIGH_BIT = 1 << 255;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
address zeroExAddress,
|
address zeroExAddress
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
FixinEIP712(zeroExAddress)
|
FixinEIP712(zeroExAddress)
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{
|
{
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,10 @@ abstract contract NativeOrdersSettlement is
|
|||||||
IEtherTokenV06 weth,
|
IEtherTokenV06 weth,
|
||||||
IStaking staking,
|
IStaking staking,
|
||||||
FeeCollectorController feeCollectorController,
|
FeeCollectorController feeCollectorController,
|
||||||
uint32 protocolFeeMultiplier,
|
uint32 protocolFeeMultiplier
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
NativeOrdersCancellation(zeroExAddress, greedyTokensBloomFilter)
|
NativeOrdersCancellation(zeroExAddress)
|
||||||
NativeOrdersProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
|
NativeOrdersProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
|
||||||
{
|
{
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
|
@ -22,28 +22,13 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
|
||||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||||
import "../features/interfaces/ITokenSpenderFeature.sol";
|
|
||||||
import "../errors/LibSpenderRichErrors.sol";
|
|
||||||
import "../external/FeeCollector.sol";
|
|
||||||
import "../vendor/v3/IStaking.sol";
|
|
||||||
import "../vendor/v3/IStaking.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev Helpers for moving tokens around.
|
/// @dev Helpers for moving tokens around.
|
||||||
abstract contract FixinTokenSpender {
|
abstract contract FixinTokenSpender {
|
||||||
using LibRichErrorsV06 for bytes;
|
|
||||||
|
|
||||||
// Mask of the lower 20 bytes of a bytes32.
|
// Mask of the lower 20 bytes of a bytes32.
|
||||||
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
|
uint256 constant private ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
|
||||||
/// @dev A bloom filter for tokens that consume all gas when `transferFrom()` fails.
|
|
||||||
bytes32 public immutable GREEDY_TOKENS_BLOOM_FILTER;
|
|
||||||
|
|
||||||
/// @param greedyTokensBloomFilter The bloom filter for all greedy tokens.
|
|
||||||
constructor(bytes32 greedyTokensBloomFilter)
|
|
||||||
internal
|
|
||||||
{
|
|
||||||
GREEDY_TOKENS_BLOOM_FILTER = greedyTokensBloomFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Transfers ERC20 tokens from `owner` to `to`.
|
/// @dev Transfers ERC20 tokens from `owner` to `to`.
|
||||||
/// @param token The token to spend.
|
/// @param token The token to spend.
|
||||||
@ -58,29 +43,8 @@ abstract contract FixinTokenSpender {
|
|||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
bool success;
|
|
||||||
bytes memory revertData;
|
|
||||||
|
|
||||||
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
|
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
|
||||||
|
|
||||||
// If the token eats all gas when failing, we do not want to perform
|
|
||||||
// optimistic fall through to the old AllowanceTarget contract if the
|
|
||||||
// direct transferFrom() fails.
|
|
||||||
if (_isTokenPossiblyGreedy(token)) {
|
|
||||||
// If the token does not have a direct allowance on us then we use
|
|
||||||
// the allowance target.
|
|
||||||
if (token.allowance(owner, address(this)) < amount) {
|
|
||||||
_transferFromLegacyAllowanceTarget(
|
|
||||||
token,
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
""
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
assembly {
|
assembly {
|
||||||
let ptr := mload(0x40) // free memory pointer
|
let ptr := mload(0x40) // free memory pointer
|
||||||
|
|
||||||
@ -90,20 +54,18 @@ abstract contract FixinTokenSpender {
|
|||||||
mstore(add(ptr, 0x24), and(to, ADDRESS_MASK))
|
mstore(add(ptr, 0x24), and(to, ADDRESS_MASK))
|
||||||
mstore(add(ptr, 0x44), amount)
|
mstore(add(ptr, 0x44), amount)
|
||||||
|
|
||||||
success := call(
|
let success := call(
|
||||||
gas(),
|
gas(),
|
||||||
and(token, ADDRESS_MASK),
|
and(token, ADDRESS_MASK),
|
||||||
0,
|
0,
|
||||||
ptr,
|
ptr,
|
||||||
0x64,
|
0x64,
|
||||||
0,
|
ptr,
|
||||||
0
|
32
|
||||||
)
|
)
|
||||||
|
|
||||||
let rdsize := returndatasize()
|
let rdsize := returndatasize()
|
||||||
|
|
||||||
returndatacopy(add(ptr, 0x20), 0, rdsize) // reuse memory
|
|
||||||
|
|
||||||
// Check for ERC20 success. ERC20 tokens should return a boolean,
|
// Check for ERC20 success. ERC20 tokens should return a boolean,
|
||||||
// but some don't. We accept 0-length return data as success, or at
|
// but some don't. We accept 0-length return data as success, or at
|
||||||
// least 32 bytes that starts with a 32-byte boolean true.
|
// least 32 bytes that starts with a 32-byte boolean true.
|
||||||
@ -113,30 +75,16 @@ abstract contract FixinTokenSpender {
|
|||||||
iszero(rdsize), // no return data, or
|
iszero(rdsize), // no return data, or
|
||||||
and(
|
and(
|
||||||
iszero(lt(rdsize, 32)), // at least 32 bytes
|
iszero(lt(rdsize, 32)), // at least 32 bytes
|
||||||
eq(mload(add(ptr, 0x20)), 1) // starts with uint256(1)
|
eq(mload(ptr), 1) // starts with uint256(1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if iszero(success) {
|
if iszero(success) {
|
||||||
// revertData is a bytes, so length-prefixed data
|
returndatacopy(ptr, 0, rdsize)
|
||||||
mstore(ptr, rdsize)
|
revert(ptr, rdsize)
|
||||||
revertData := ptr
|
|
||||||
|
|
||||||
// update free memory pointer (ptr + 32-byte length + return data)
|
|
||||||
mstore(0x40, add(add(ptr, 0x20), rdsize))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
_transferFromLegacyAllowanceTarget(
|
|
||||||
token,
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
revertData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
|
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
|
||||||
@ -157,53 +105,4 @@ abstract contract FixinTokenSpender {
|
|||||||
token.balanceOf(owner)
|
token.balanceOf(owner)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Check if a token possibly belongs to the `GREEDY_TOKENS_BLOOM_FILTER`
|
|
||||||
/// bloom filter.
|
|
||||||
function _isTokenPossiblyGreedy(IERC20TokenV06 token)
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (bool isPossiblyGreedy)
|
|
||||||
{
|
|
||||||
// The hash is given by:
|
|
||||||
// (1 << (keccak256(token) % 256)) | (1 << (token % 256))
|
|
||||||
bytes32 h;
|
|
||||||
assembly {
|
|
||||||
mstore(0, token)
|
|
||||||
h := or(shl(mod(keccak256(0, 32), 256), 1), shl(mod(token, 256), 1))
|
|
||||||
}
|
|
||||||
return (h & GREEDY_TOKENS_BLOOM_FILTER) == h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Transfer tokens using the legacy allowance target instead of
|
|
||||||
/// allowances directly set on the exchange proxy.
|
|
||||||
function _transferFromLegacyAllowanceTarget(
|
|
||||||
IERC20TokenV06 token,
|
|
||||||
address owner,
|
|
||||||
address to,
|
|
||||||
uint256 amount,
|
|
||||||
bytes memory initialRevertData
|
|
||||||
)
|
|
||||||
private
|
|
||||||
{
|
|
||||||
// Try the old AllowanceTarget.
|
|
||||||
try ITokenSpenderFeature(address(this))._spendERC20Tokens(
|
|
||||||
token,
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount
|
|
||||||
) {
|
|
||||||
} catch (bytes memory revertData) {
|
|
||||||
// Bubble up the first error message. (In general, the fallback to the
|
|
||||||
// allowance target is opportunistic. We ignore the specific error
|
|
||||||
// message if it fails.)
|
|
||||||
LibSpenderRichErrors.SpenderERC20TransferFromFailedError(
|
|
||||||
address(token),
|
|
||||||
owner,
|
|
||||||
to,
|
|
||||||
amount,
|
|
||||||
initialRevertData.length != 0 ? initialRevertData : revertData
|
|
||||||
).rrevert();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,9 @@ pragma experimental ABIEncoderV2;
|
|||||||
|
|
||||||
import "../ZeroEx.sol";
|
import "../ZeroEx.sol";
|
||||||
import "../features/interfaces/IOwnableFeature.sol";
|
import "../features/interfaces/IOwnableFeature.sol";
|
||||||
import "../features/TokenSpenderFeature.sol";
|
|
||||||
import "../features/TransformERC20Feature.sol";
|
import "../features/TransformERC20Feature.sol";
|
||||||
import "../features/MetaTransactionsFeature.sol";
|
import "../features/MetaTransactionsFeature.sol";
|
||||||
import "../features/NativeOrdersFeature.sol";
|
import "../features/NativeOrdersFeature.sol";
|
||||||
import "../external/AllowanceTarget.sol";
|
|
||||||
import "./InitialMigration.sol";
|
import "./InitialMigration.sol";
|
||||||
|
|
||||||
|
|
||||||
@ -39,7 +37,6 @@ contract FullMigration {
|
|||||||
struct Features {
|
struct Features {
|
||||||
SimpleFunctionRegistryFeature registry;
|
SimpleFunctionRegistryFeature registry;
|
||||||
OwnableFeature ownable;
|
OwnableFeature ownable;
|
||||||
TokenSpenderFeature tokenSpender;
|
|
||||||
TransformERC20Feature transformERC20;
|
TransformERC20Feature transformERC20;
|
||||||
MetaTransactionsFeature metaTransactions;
|
MetaTransactionsFeature metaTransactions;
|
||||||
NativeOrdersFeature nativeOrders;
|
NativeOrdersFeature nativeOrders;
|
||||||
@ -107,7 +104,7 @@ contract FullMigration {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add features.
|
// Add features.
|
||||||
_addFeatures(zeroEx, owner, features, migrateOpts);
|
_addFeatures(zeroEx, features, migrateOpts);
|
||||||
|
|
||||||
// Transfer ownership to the real owner.
|
// Transfer ownership to the real owner.
|
||||||
IOwnableFeature(address(zeroEx)).transferOwnership(owner);
|
IOwnableFeature(address(zeroEx)).transferOwnership(owner);
|
||||||
@ -132,36 +129,16 @@ contract FullMigration {
|
|||||||
|
|
||||||
/// @dev Deploy and register features to the ZeroEx contract.
|
/// @dev Deploy and register features to the ZeroEx contract.
|
||||||
/// @param zeroEx The bootstrapped ZeroEx contract.
|
/// @param zeroEx The bootstrapped ZeroEx contract.
|
||||||
/// @param owner The ultimate owner of the ZeroEx contract.
|
|
||||||
/// @param features Features to add to the proxy.
|
/// @param features Features to add to the proxy.
|
||||||
/// @param migrateOpts Parameters needed to initialize features.
|
/// @param migrateOpts Parameters needed to initialize features.
|
||||||
function _addFeatures(
|
function _addFeatures(
|
||||||
ZeroEx zeroEx,
|
ZeroEx zeroEx,
|
||||||
address owner,
|
|
||||||
Features memory features,
|
Features memory features,
|
||||||
MigrateOpts memory migrateOpts
|
MigrateOpts memory migrateOpts
|
||||||
)
|
)
|
||||||
private
|
private
|
||||||
{
|
{
|
||||||
IOwnableFeature ownable = IOwnableFeature(address(zeroEx));
|
IOwnableFeature ownable = IOwnableFeature(address(zeroEx));
|
||||||
// TokenSpenderFeature
|
|
||||||
{
|
|
||||||
// Create the allowance target.
|
|
||||||
AllowanceTarget allowanceTarget = new AllowanceTarget();
|
|
||||||
// Let the ZeroEx contract use the allowance target.
|
|
||||||
allowanceTarget.addAuthorizedAddress(address(zeroEx));
|
|
||||||
// Transfer ownership of the allowance target to the (real) owner.
|
|
||||||
allowanceTarget.transferOwnership(owner);
|
|
||||||
// Register the feature.
|
|
||||||
ownable.migrate(
|
|
||||||
address(features.tokenSpender),
|
|
||||||
abi.encodeWithSelector(
|
|
||||||
TokenSpenderFeature.migrate.selector,
|
|
||||||
allowanceTarget
|
|
||||||
),
|
|
||||||
address(this)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// TransformERC20Feature
|
// TransformERC20Feature
|
||||||
{
|
{
|
||||||
// Register the feature.
|
// Register the feature.
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "./LibStorage.sol";
|
|
||||||
import "../external/IAllowanceTarget.sol";
|
|
||||||
|
|
||||||
|
|
||||||
/// @dev Storage helpers for the `TokenSpender` feature.
|
|
||||||
library LibTokenSpenderStorage {
|
|
||||||
|
|
||||||
/// @dev Storage bucket for this feature.
|
|
||||||
struct Storage {
|
|
||||||
// Allowance target contract.
|
|
||||||
IAllowanceTarget allowanceTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Get the storage bucket for this contract.
|
|
||||||
function getStorage() internal pure returns (Storage storage stor) {
|
|
||||||
uint256 storageSlot = LibStorage.getStorageSlot(
|
|
||||||
LibStorage.StorageId.TokenSpender
|
|
||||||
);
|
|
||||||
// Dip into assembly to change the slot pointed to by the local
|
|
||||||
// variable `stor`.
|
|
||||||
// See https://solidity.readthedocs.io/en/v0.6.8/assembly.html?highlight=slot#access-to-external-variables-functions-and-libraries
|
|
||||||
assembly { stor_slot := storageSlot }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
Copyright 2021 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
|
|||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./IBridgeAdapter.sol";
|
import "./IBridgeAdapter.sol";
|
||||||
import "./BridgeSource.sol";
|
import "./BridgeProtocols.sol";
|
||||||
import "./mixins/MixinBalancer.sol";
|
import "./mixins/MixinBalancer.sol";
|
||||||
import "./mixins/MixinBancor.sol";
|
import "./mixins/MixinBancor.sol";
|
||||||
import "./mixins/MixinCoFiX.sol";
|
import "./mixins/MixinCoFiX.sol";
|
||||||
@ -32,9 +32,9 @@ import "./mixins/MixinDodoV2.sol";
|
|||||||
import "./mixins/MixinKyber.sol";
|
import "./mixins/MixinKyber.sol";
|
||||||
import "./mixins/MixinMooniswap.sol";
|
import "./mixins/MixinMooniswap.sol";
|
||||||
import "./mixins/MixinMStable.sol";
|
import "./mixins/MixinMStable.sol";
|
||||||
|
import "./mixins/MixinNerve.sol";
|
||||||
import "./mixins/MixinOasis.sol";
|
import "./mixins/MixinOasis.sol";
|
||||||
import "./mixins/MixinShell.sol";
|
import "./mixins/MixinShell.sol";
|
||||||
import "./mixins/MixinSushiswap.sol";
|
|
||||||
import "./mixins/MixinUniswap.sol";
|
import "./mixins/MixinUniswap.sol";
|
||||||
import "./mixins/MixinUniswapV2.sol";
|
import "./mixins/MixinUniswapV2.sol";
|
||||||
import "./mixins/MixinZeroExBridge.sol";
|
import "./mixins/MixinZeroExBridge.sol";
|
||||||
@ -51,9 +51,9 @@ contract BridgeAdapter is
|
|||||||
MixinKyber,
|
MixinKyber,
|
||||||
MixinMooniswap,
|
MixinMooniswap,
|
||||||
MixinMStable,
|
MixinMStable,
|
||||||
|
MixinNerve,
|
||||||
MixinOasis,
|
MixinOasis,
|
||||||
MixinShell,
|
MixinShell,
|
||||||
MixinSushiswap,
|
|
||||||
MixinUniswap,
|
MixinUniswap,
|
||||||
MixinUniswapV2,
|
MixinUniswapV2,
|
||||||
MixinZeroExBridge
|
MixinZeroExBridge
|
||||||
@ -70,9 +70,9 @@ contract BridgeAdapter is
|
|||||||
MixinKyber(weth)
|
MixinKyber(weth)
|
||||||
MixinMooniswap(weth)
|
MixinMooniswap(weth)
|
||||||
MixinMStable()
|
MixinMStable()
|
||||||
|
MixinNerve()
|
||||||
MixinOasis()
|
MixinOasis()
|
||||||
MixinShell()
|
MixinShell()
|
||||||
MixinSushiswap()
|
|
||||||
MixinUniswap(weth)
|
MixinUniswap(weth)
|
||||||
MixinUniswapV2()
|
MixinUniswapV2()
|
||||||
MixinZeroExBridge()
|
MixinZeroExBridge()
|
||||||
@ -88,109 +88,106 @@ contract BridgeAdapter is
|
|||||||
override
|
override
|
||||||
returns (uint256 boughtAmount)
|
returns (uint256 boughtAmount)
|
||||||
{
|
{
|
||||||
if (order.source == BridgeSource.CURVE ||
|
uint128 protocolId = uint128(uint256(order.source) >> 128);
|
||||||
order.source == BridgeSource.SWERVE ||
|
if (protocolId == BridgeProtocols.CURVE) {
|
||||||
order.source == BridgeSource.SNOWSWAP) {
|
|
||||||
boughtAmount = _tradeCurve(
|
boughtAmount = _tradeCurve(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.SUSHISWAP) {
|
} else if (protocolId == BridgeProtocols.UNISWAPV2) {
|
||||||
boughtAmount = _tradeSushiswap(
|
|
||||||
buyToken,
|
|
||||||
sellAmount,
|
|
||||||
order.bridgeData
|
|
||||||
);
|
|
||||||
} else if (order.source == BridgeSource.UNISWAPV2 ||
|
|
||||||
order.source == BridgeSource.LINKSWAP) {
|
|
||||||
boughtAmount = _tradeUniswapV2(
|
boughtAmount = _tradeUniswapV2(
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.UNISWAP) {
|
} else if (protocolId == BridgeProtocols.UNISWAP) {
|
||||||
boughtAmount = _tradeUniswap(
|
boughtAmount = _tradeUniswap(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.BALANCER ||
|
} else if (protocolId == BridgeProtocols.BALANCER) {
|
||||||
order.source == BridgeSource.CREAM) {
|
|
||||||
boughtAmount = _tradeBalancer(
|
boughtAmount = _tradeBalancer(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.KYBER) {
|
} else if (protocolId == BridgeProtocols.KYBER) {
|
||||||
boughtAmount = _tradeKyber(
|
boughtAmount = _tradeKyber(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.MOONISWAP) {
|
} else if (protocolId == BridgeProtocols.MOONISWAP) {
|
||||||
boughtAmount = _tradeMooniswap(
|
boughtAmount = _tradeMooniswap(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.MSTABLE) {
|
} else if (protocolId == BridgeProtocols.MSTABLE) {
|
||||||
boughtAmount = _tradeMStable(
|
boughtAmount = _tradeMStable(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.OASIS) {
|
} else if (protocolId == BridgeProtocols.OASIS) {
|
||||||
boughtAmount = _tradeOasis(
|
boughtAmount = _tradeOasis(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.SHELL) {
|
} else if (protocolId == BridgeProtocols.SHELL) {
|
||||||
boughtAmount = _tradeShell(
|
boughtAmount = _tradeShell(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.DODO) {
|
} else if (protocolId == BridgeProtocols.DODO) {
|
||||||
boughtAmount = _tradeDodo(
|
boughtAmount = _tradeDodo(
|
||||||
sellToken,
|
sellToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.DODOV2) {
|
} else if (protocolId == BridgeProtocols.DODOV2) {
|
||||||
boughtAmount = _tradeDodoV2(
|
boughtAmount = _tradeDodoV2(
|
||||||
sellToken,
|
sellToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.CRYPTOCOM) {
|
} else if (protocolId == BridgeProtocols.CRYPTOCOM) {
|
||||||
boughtAmount = _tradeCryptoCom(
|
boughtAmount = _tradeCryptoCom(
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.BANCOR) {
|
} else if (protocolId == BridgeProtocols.BANCOR) {
|
||||||
boughtAmount = _tradeBancor(
|
boughtAmount = _tradeBancor(
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
} else if (order.source == BridgeSource.COFIX) {
|
} else if (protocolId == BridgeProtocols.COFIX) {
|
||||||
boughtAmount = _tradeCoFiX(
|
boughtAmount = _tradeCoFiX(
|
||||||
sellToken,
|
sellToken,
|
||||||
buyToken,
|
buyToken,
|
||||||
sellAmount,
|
sellAmount,
|
||||||
order.bridgeData
|
order.bridgeData
|
||||||
);
|
);
|
||||||
|
} else if (protocolId == BridgeProtocols.NERVE) {
|
||||||
|
boughtAmount = _tradeNerve(
|
||||||
|
sellToken,
|
||||||
|
sellAmount,
|
||||||
|
order.bridgeData
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
boughtAmount = _tradeZeroExBridge(
|
boughtAmount = _tradeZeroExBridge(
|
||||||
sellToken,
|
sellToken,
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
// 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/IERC20TokenV06.sol";
|
||||||
|
|
||||||
|
|
||||||
|
library BridgeProtocols {
|
||||||
|
// A incrementally increasing, append-only list of protocol IDs.
|
||||||
|
// We don't use an enum so solidity doesn't throw when we pass in a
|
||||||
|
// new protocol ID that hasn't been rolled up yet.
|
||||||
|
uint128 internal constant UNKNOWN = 0;
|
||||||
|
uint128 internal constant CURVE = 1;
|
||||||
|
uint128 internal constant UNISWAPV2 = 2;
|
||||||
|
uint128 internal constant UNISWAP = 3;
|
||||||
|
uint128 internal constant BALANCER = 4;
|
||||||
|
uint128 internal constant KYBER = 5;
|
||||||
|
uint128 internal constant MOONISWAP = 6;
|
||||||
|
uint128 internal constant MSTABLE = 7;
|
||||||
|
uint128 internal constant OASIS = 8;
|
||||||
|
uint128 internal constant SHELL = 9;
|
||||||
|
uint128 internal constant DODO = 10;
|
||||||
|
uint128 internal constant DODOV2 = 11;
|
||||||
|
uint128 internal constant CRYPTOCOM = 12;
|
||||||
|
uint128 internal constant BANCOR = 13;
|
||||||
|
uint128 internal constant COFIX = 14;
|
||||||
|
uint128 internal constant NERVE = 15;
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
|
|
||||||
library BridgeSource {
|
|
||||||
uint256 constant internal BALANCER = 0;
|
|
||||||
uint256 constant internal BANCOR = 1;
|
|
||||||
uint256 constant internal COFIX = 2;
|
|
||||||
uint256 constant internal CURVE = 3;
|
|
||||||
uint256 constant internal CREAM = 4;
|
|
||||||
uint256 constant internal CRYPTOCOM = 5;
|
|
||||||
uint256 constant internal DODO = 6;
|
|
||||||
uint256 constant internal KYBER = 7;
|
|
||||||
uint256 constant internal LIQUIDITYPROVIDER = 8;
|
|
||||||
uint256 constant internal MOONISWAP = 9;
|
|
||||||
uint256 constant internal MSTABLE = 10;
|
|
||||||
uint256 constant internal OASIS = 11;
|
|
||||||
uint256 constant internal SHELL = 12;
|
|
||||||
uint256 constant internal SNOWSWAP = 13;
|
|
||||||
uint256 constant internal SUSHISWAP = 14;
|
|
||||||
uint256 constant internal SWERVE = 15;
|
|
||||||
uint256 constant internal UNISWAP = 16;
|
|
||||||
uint256 constant internal UNISWAPV2 = 17;
|
|
||||||
uint256 constant internal DODOV2 = 18;
|
|
||||||
uint256 constant internal LINKSWAP = 19;
|
|
||||||
// New sources should be APPENDED to this list, taking the next highest
|
|
||||||
// integer value.
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
Copyright 2021 ZeroEx Intl.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -26,20 +26,24 @@ import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
|||||||
interface IBridgeAdapter {
|
interface IBridgeAdapter {
|
||||||
|
|
||||||
struct BridgeOrder {
|
struct BridgeOrder {
|
||||||
uint256 source;
|
// Upper 16 bytes: uint128 protocol ID (right-aligned)
|
||||||
|
// Lower 16 bytes: ASCII source name (left-aligned)
|
||||||
|
bytes32 source;
|
||||||
uint256 takerTokenAmount;
|
uint256 takerTokenAmount;
|
||||||
uint256 makerTokenAmount;
|
uint256 makerTokenAmount;
|
||||||
bytes bridgeData;
|
bytes bridgeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Emitted when tokens are swapped with an external source.
|
/// @dev Emitted when tokens are swapped with an external source.
|
||||||
/// @param source The unique ID for the source. See `BridgeSource.sol`
|
/// @param source A unique ID for the source, where the upper 16 bytes
|
||||||
|
/// encodes the (right-aligned) uint128 protocol ID and the
|
||||||
|
/// lower 16 bytes encodes an ASCII source name.
|
||||||
/// @param inputToken The token the bridge is converting from.
|
/// @param inputToken The token the bridge is converting from.
|
||||||
/// @param outputToken The token the bridge is converting to.
|
/// @param outputToken The token the bridge is converting to.
|
||||||
/// @param inputTokenAmount Amount of input token sold.
|
/// @param inputTokenAmount Amount of input token sold.
|
||||||
/// @param outputTokenAmount Amount of output token bought.
|
/// @param outputTokenAmount Amount of output token bought.
|
||||||
event BridgeFill(
|
event BridgeFill(
|
||||||
uint256 source,
|
bytes32 source,
|
||||||
IERC20TokenV06 inputToken,
|
IERC20TokenV06 inputToken,
|
||||||
IERC20TokenV06 outputToken,
|
IERC20TokenV06 outputToken,
|
||||||
uint256 inputTokenAmount,
|
uint256 inputTokenAmount,
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright 2020 ZeroEx Intl.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity ^0.6.5;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
||||||
|
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
|
||||||
|
|
||||||
|
contract MixinNerve {
|
||||||
|
|
||||||
|
using LibERC20TokenV06 for IERC20TokenV06;
|
||||||
|
using LibSafeMathV06 for uint256;
|
||||||
|
using LibRichErrorsV06 for bytes;
|
||||||
|
|
||||||
|
|
||||||
|
struct NerveBridgeData {
|
||||||
|
address pool;
|
||||||
|
bytes4 exchangeFunctionSelector;
|
||||||
|
int128 fromCoinIdx;
|
||||||
|
int128 toCoinIdx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _tradeNerve(
|
||||||
|
IERC20TokenV06 sellToken,
|
||||||
|
uint256 sellAmount,
|
||||||
|
bytes memory bridgeData
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
returns (uint256 boughtAmount)
|
||||||
|
{
|
||||||
|
// Basically a Curve fork but the swap option has a deadline
|
||||||
|
|
||||||
|
// Decode the bridge data to get the Curve metadata.
|
||||||
|
NerveBridgeData memory data = abi.decode(bridgeData, (NerveBridgeData));
|
||||||
|
sellToken.approveIfBelow(data.pool, sellAmount);
|
||||||
|
(bool success, bytes memory resultData) =
|
||||||
|
data.pool.call(abi.encodeWithSelector(
|
||||||
|
data.exchangeFunctionSelector,
|
||||||
|
data.fromCoinIdx,
|
||||||
|
data.toCoinIdx,
|
||||||
|
// dx
|
||||||
|
sellAmount,
|
||||||
|
// min dy
|
||||||
|
1,
|
||||||
|
// deadline
|
||||||
|
block.timestamp
|
||||||
|
));
|
||||||
|
if (!success) {
|
||||||
|
resultData.rrevert();
|
||||||
|
}
|
||||||
|
return abi.decode(resultData, (uint256));
|
||||||
|
}
|
||||||
|
}
|
@ -1,75 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
|
|
||||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
|
|
||||||
import "./MixinUniswapV2.sol";
|
|
||||||
|
|
||||||
contract MixinSushiswap {
|
|
||||||
|
|
||||||
using LibERC20TokenV06 for IERC20TokenV06;
|
|
||||||
|
|
||||||
function _tradeSushiswap(
|
|
||||||
IERC20TokenV06 buyToken,
|
|
||||||
uint256 sellAmount,
|
|
||||||
bytes memory bridgeData
|
|
||||||
)
|
|
||||||
internal
|
|
||||||
returns (uint256 boughtAmount)
|
|
||||||
{
|
|
||||||
IERC20TokenV06[] memory path;
|
|
||||||
IUniswapV2Router02 router;
|
|
||||||
{
|
|
||||||
address[] memory _path;
|
|
||||||
(router, _path) =
|
|
||||||
abi.decode(bridgeData, (IUniswapV2Router02, address[]));
|
|
||||||
// To get around `abi.decode()` not supporting interface array types.
|
|
||||||
assembly { path := _path }
|
|
||||||
}
|
|
||||||
|
|
||||||
require(path.length >= 2, "MixinSushiswap/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
|
|
||||||
require(
|
|
||||||
path[path.length - 1] == buyToken,
|
|
||||||
"MixinSushiswap/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
|
|
||||||
);
|
|
||||||
// Grant the Uniswap router an allowance to sell the first token.
|
|
||||||
path[0].approveIfBelow(
|
|
||||||
address(router),
|
|
||||||
sellAmount
|
|
||||||
);
|
|
||||||
|
|
||||||
uint[] memory amounts = router.swapExactTokensForTokens(
|
|
||||||
// Sell all tokens we hold.
|
|
||||||
sellAmount,
|
|
||||||
// Minimum buy amount.
|
|
||||||
1,
|
|
||||||
// Convert to `buyToken` along this path.
|
|
||||||
path,
|
|
||||||
// Recipient is `this`.
|
|
||||||
address(this),
|
|
||||||
// Expires after this block.
|
|
||||||
block.timestamp
|
|
||||||
);
|
|
||||||
return amounts[amounts.length-1];
|
|
||||||
}
|
|
||||||
}
|
|
@ -26,12 +26,7 @@ import "../src/fixins/FixinTokenSpender.sol";
|
|||||||
contract TestFixinTokenSpender is
|
contract TestFixinTokenSpender is
|
||||||
FixinTokenSpender
|
FixinTokenSpender
|
||||||
{
|
{
|
||||||
uint256 constant private TRIGGER_FALLBACK_SUCCESS_AMOUNT = 1340;
|
constructor() public {}
|
||||||
|
|
||||||
constructor(bytes32 greedyTokensBloomFilter)
|
|
||||||
public
|
|
||||||
FixinTokenSpender(greedyTokensBloomFilter)
|
|
||||||
{}
|
|
||||||
|
|
||||||
function transferERC20Tokens(
|
function transferERC20Tokens(
|
||||||
IERC20TokenV06 token,
|
IERC20TokenV06 token,
|
||||||
@ -56,21 +51,6 @@ contract TestFixinTokenSpender is
|
|||||||
uint256 amount
|
uint256 amount
|
||||||
);
|
);
|
||||||
|
|
||||||
// This is called as a fallback when the original transferFrom() fails.
|
|
||||||
function _spendERC20Tokens(
|
|
||||||
IERC20TokenV06 token,
|
|
||||||
address owner,
|
|
||||||
address to,
|
|
||||||
uint256 amount
|
|
||||||
)
|
|
||||||
external
|
|
||||||
{
|
|
||||||
require(amount == TRIGGER_FALLBACK_SUCCESS_AMOUNT,
|
|
||||||
"TokenSpenderFallback/FAILURE_AMOUNT");
|
|
||||||
|
|
||||||
emit FallbackCalled(address(token), owner, to, amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSpendableERC20BalanceOf(
|
function getSpendableERC20BalanceOf(
|
||||||
IERC20TokenV06 token,
|
IERC20TokenV06 token,
|
||||||
address owner
|
address owner
|
||||||
@ -81,12 +61,4 @@ contract TestFixinTokenSpender is
|
|||||||
{
|
{
|
||||||
return _getSpendableERC20BalanceOf(token, owner);
|
return _getSpendableERC20BalanceOf(token, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTokenPossiblyGreedy(IERC20TokenV06 token)
|
|
||||||
external
|
|
||||||
view
|
|
||||||
returns (bool)
|
|
||||||
{
|
|
||||||
return _isTokenPossiblyGreedy(token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,7 @@ contract TestMetaTransactionsNativeOrdersFeature is
|
|||||||
IEtherTokenV06(0),
|
IEtherTokenV06(0),
|
||||||
IStaking(0),
|
IStaking(0),
|
||||||
FeeCollectorController(address(new TestFeeCollectorController())),
|
FeeCollectorController(address(new TestFeeCollectorController())),
|
||||||
0,
|
0
|
||||||
bytes32(0)
|
|
||||||
)
|
)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ contract TestMetaTransactionsTransformERC20Feature is
|
|||||||
Transformation[] transformations
|
Transformation[] transformations
|
||||||
);
|
);
|
||||||
|
|
||||||
constructor() public TransformERC20Feature(0) {}
|
constructor() public TransformERC20Feature() {}
|
||||||
|
|
||||||
function _transformERC20(TransformERC20Args memory args)
|
function _transformERC20(TransformERC20Args memory args)
|
||||||
public
|
public
|
||||||
|
@ -13,8 +13,7 @@ contract TestNativeOrdersFeature is
|
|||||||
IEtherTokenV06 weth,
|
IEtherTokenV06 weth,
|
||||||
IStaking staking,
|
IStaking staking,
|
||||||
FeeCollectorController _feeCollectorController, // Unused but necessary for artifact compatibility.
|
FeeCollectorController _feeCollectorController, // Unused but necessary for artifact compatibility.
|
||||||
uint32 protocolFeeMultiplier,
|
uint32 protocolFeeMultiplier
|
||||||
bytes32 greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
NativeOrdersFeature(
|
NativeOrdersFeature(
|
||||||
@ -22,8 +21,7 @@ contract TestNativeOrdersFeature is
|
|||||||
weth,
|
weth,
|
||||||
staking,
|
staking,
|
||||||
FeeCollectorController(address(new TestFeeCollectorController())),
|
FeeCollectorController(address(new TestFeeCollectorController())),
|
||||||
protocolFeeMultiplier,
|
protocolFeeMultiplier
|
||||||
greedyTokensBloomFilter
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// solhint-disable no-empty-blocks
|
// solhint-disable no-empty-blocks
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6.5;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "../src/features/TokenSpenderFeature.sol";
|
|
||||||
|
|
||||||
contract TestTokenSpender is
|
|
||||||
TokenSpenderFeature
|
|
||||||
{
|
|
||||||
modifier onlySelf() override {
|
|
||||||
_;
|
|
||||||
}
|
|
||||||
}
|
|
@ -30,5 +30,5 @@ contract TestTransformERC20 is
|
|||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() public TransformERC20Feature(0) {}
|
constructor() public TransformERC20Feature() {}
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,9 @@
|
|||||||
"rollback": "node ./lib/scripts/rollback.js"
|
"rollback": "node ./lib/scripts/rollback.js"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITokenSpenderFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,TokenSpenderFeature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
|
"publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IERC20Transformer,IOwnableFeature,ISimpleFunctionRegistryFeature,ITransformERC20Feature,FillQuoteTransformer,PayTakerTransformer,PositiveSlippageFeeTransformer,WethTransformer,OwnableFeature,SimpleFunctionRegistryFeature,TransformERC20Feature,AffiliateFeeTransformer,MetaTransactionsFeature,LogMetadataTransformer,BridgeAdapter,LiquidityProviderFeature,ILiquidityProviderFeature,NativeOrdersFeature,INativeOrdersFeature,FeeCollectorController,FeeCollector,CurveLiquidityProvider,BatchFillNativeOrdersFeature,IBatchFillNativeOrdersFeature,MultiplexFeature,IMultiplexFeature",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeSource|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IAllowanceTarget|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinOasis|MixinShell|MixinSushiswap|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|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|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpenderFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
"abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|BatchFillNativeOrdersFeature|BootstrapFeature|BridgeAdapter|BridgeProtocols|CurveLiquidityProvider|FeeCollector|FeeCollectorController|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinProtocolFees|FixinReentrancyGuard|FixinTokenSpender|FlashWallet|FullMigration|IBatchFillNativeOrdersFeature|IBootstrapFeature|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IFeature|IFlashWallet|ILiquidityProvider|ILiquidityProviderFeature|ILiquidityProviderSandbox|IMetaTransactionsFeature|IMooniswapPool|IMultiplexFeature|INativeOrdersEvents|INativeOrdersFeature|IOwnableFeature|IPancakeSwapFeature|ISimpleFunctionRegistryFeature|IStaking|ITestSimpleFunctionRegistryFeature|ITokenSpenderFeature|ITransformERC20Feature|IUniswapFeature|IUniswapV2Pair|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibFeeCollector|LibLiquidityProviderRichErrors|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibNativeOrder|LibNativeOrdersRichErrors|LibNativeOrdersStorage|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibReentrancyGuardStorage|LibSignature|LibSignatureRichErrors|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|LiquidityProviderFeature|LiquidityProviderSandbox|LogMetadataTransformer|MetaTransactionsFeature|MixinBalancer|MixinBancor|MixinCoFiX|MixinCryptoCom|MixinCurve|MixinDodo|MixinDodoV2|MixinKyber|MixinMStable|MixinMooniswap|MixinNerve|MixinOasis|MixinShell|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|MooniswapLiquidityProvider|MultiplexFeature|NativeOrdersCancellation|NativeOrdersFeature|NativeOrdersInfo|NativeOrdersProtocolFees|NativeOrdersSettlement|OwnableFeature|PancakeSwapFeature|PayTakerTransformer|PermissionlessTransformerDeployer|PositiveSlippageFeeTransformer|SimpleFunctionRegistryFeature|TestBridge|TestCallTarget|TestCurve|TestDelegateCaller|TestFeeCollectorController|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFixinProtocolFees|TestFixinTokenSpender|TestFullMigration|TestInitialMigration|TestLibNativeOrder|TestLibSignature|TestLiquidityProvider|TestMetaTransactionsNativeOrdersFeature|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestMooniswap|TestNativeOrdersFeature|TestPermissionlessTransformerDeployerSuicidal|TestPermissionlessTransformerDeployerTransformer|TestRfqOriginRegistration|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestStaking|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TransformERC20Feature|Transformer|TransformerDeployer|UniswapFeature|WethTransformer|ZeroEx|ZeroExOptimized).json"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -23,7 +23,6 @@ import * as INativeOrdersFeature from '../generated-artifacts/INativeOrdersFeatu
|
|||||||
import * as InitialMigration from '../generated-artifacts/InitialMigration.json';
|
import * as InitialMigration from '../generated-artifacts/InitialMigration.json';
|
||||||
import * as IOwnableFeature from '../generated-artifacts/IOwnableFeature.json';
|
import * as IOwnableFeature from '../generated-artifacts/IOwnableFeature.json';
|
||||||
import * as ISimpleFunctionRegistryFeature from '../generated-artifacts/ISimpleFunctionRegistryFeature.json';
|
import * as ISimpleFunctionRegistryFeature from '../generated-artifacts/ISimpleFunctionRegistryFeature.json';
|
||||||
import * as ITokenSpenderFeature from '../generated-artifacts/ITokenSpenderFeature.json';
|
|
||||||
import * as ITransformERC20Feature from '../generated-artifacts/ITransformERC20Feature.json';
|
import * as ITransformERC20Feature from '../generated-artifacts/ITransformERC20Feature.json';
|
||||||
import * as IZeroEx from '../generated-artifacts/IZeroEx.json';
|
import * as IZeroEx from '../generated-artifacts/IZeroEx.json';
|
||||||
import * as LiquidityProviderFeature from '../generated-artifacts/LiquidityProviderFeature.json';
|
import * as LiquidityProviderFeature from '../generated-artifacts/LiquidityProviderFeature.json';
|
||||||
@ -35,7 +34,6 @@ import * as OwnableFeature from '../generated-artifacts/OwnableFeature.json';
|
|||||||
import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json';
|
import * as PayTakerTransformer from '../generated-artifacts/PayTakerTransformer.json';
|
||||||
import * as PositiveSlippageFeeTransformer from '../generated-artifacts/PositiveSlippageFeeTransformer.json';
|
import * as PositiveSlippageFeeTransformer from '../generated-artifacts/PositiveSlippageFeeTransformer.json';
|
||||||
import * as SimpleFunctionRegistryFeature from '../generated-artifacts/SimpleFunctionRegistryFeature.json';
|
import * as SimpleFunctionRegistryFeature from '../generated-artifacts/SimpleFunctionRegistryFeature.json';
|
||||||
import * as TokenSpenderFeature from '../generated-artifacts/TokenSpenderFeature.json';
|
|
||||||
import * as TransformERC20Feature from '../generated-artifacts/TransformERC20Feature.json';
|
import * as TransformERC20Feature from '../generated-artifacts/TransformERC20Feature.json';
|
||||||
import * as WethTransformer from '../generated-artifacts/WethTransformer.json';
|
import * as WethTransformer from '../generated-artifacts/WethTransformer.json';
|
||||||
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
|
import * as ZeroEx from '../generated-artifacts/ZeroEx.json';
|
||||||
@ -49,7 +47,6 @@ export const artifacts = {
|
|||||||
IERC20Transformer: IERC20Transformer as ContractArtifact,
|
IERC20Transformer: IERC20Transformer as ContractArtifact,
|
||||||
IOwnableFeature: IOwnableFeature as ContractArtifact,
|
IOwnableFeature: IOwnableFeature as ContractArtifact,
|
||||||
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
|
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
|
|
||||||
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
|
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
|
||||||
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
|
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
|
||||||
PayTakerTransformer: PayTakerTransformer as ContractArtifact,
|
PayTakerTransformer: PayTakerTransformer as ContractArtifact,
|
||||||
@ -58,7 +55,6 @@ export const artifacts = {
|
|||||||
OwnableFeature: OwnableFeature as ContractArtifact,
|
OwnableFeature: OwnableFeature as ContractArtifact,
|
||||||
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
|
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
|
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
|
||||||
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
|
|
||||||
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
|
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
|
||||||
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
|
MetaTransactionsFeature: MetaTransactionsFeature as ContractArtifact,
|
||||||
LogMetadataTransformer: LogMetadataTransformer as ContractArtifact,
|
LogMetadataTransformer: LogMetadataTransformer as ContractArtifact,
|
||||||
|
@ -41,7 +41,6 @@ export {
|
|||||||
IOwnableFeatureEvents,
|
IOwnableFeatureEvents,
|
||||||
ISimpleFunctionRegistryFeatureContract,
|
ISimpleFunctionRegistryFeatureContract,
|
||||||
ISimpleFunctionRegistryFeatureEvents,
|
ISimpleFunctionRegistryFeatureEvents,
|
||||||
ITokenSpenderFeatureContract,
|
|
||||||
ITransformERC20FeatureContract,
|
ITransformERC20FeatureContract,
|
||||||
IZeroExContract,
|
IZeroExContract,
|
||||||
LogMetadataTransformerContract,
|
LogMetadataTransformerContract,
|
||||||
|
@ -5,7 +5,6 @@ import { TxData } from 'ethereum-types';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
import { ZERO_BYTES32 } from './constants';
|
|
||||||
import {
|
import {
|
||||||
FeeCollectorControllerContract,
|
FeeCollectorControllerContract,
|
||||||
FullMigrationContract,
|
FullMigrationContract,
|
||||||
@ -15,7 +14,6 @@ import {
|
|||||||
NativeOrdersFeatureContract,
|
NativeOrdersFeatureContract,
|
||||||
OwnableFeatureContract,
|
OwnableFeatureContract,
|
||||||
SimpleFunctionRegistryFeatureContract,
|
SimpleFunctionRegistryFeatureContract,
|
||||||
TokenSpenderFeatureContract,
|
|
||||||
TransformERC20FeatureContract,
|
TransformERC20FeatureContract,
|
||||||
ZeroExContract,
|
ZeroExContract,
|
||||||
} from './wrappers';
|
} from './wrappers';
|
||||||
@ -108,7 +106,6 @@ export async function initialMigrateAsync(
|
|||||||
* Addresses of features for a full deployment of the Exchange Proxy.
|
* Addresses of features for a full deployment of the Exchange Proxy.
|
||||||
*/
|
*/
|
||||||
export interface FullFeatures extends BootstrapFeatures {
|
export interface FullFeatures extends BootstrapFeatures {
|
||||||
tokenSpender: string;
|
|
||||||
transformERC20: string;
|
transformERC20: string;
|
||||||
metaTransactions: string;
|
metaTransactions: string;
|
||||||
nativeOrders: string;
|
nativeOrders: string;
|
||||||
@ -118,7 +115,6 @@ export interface FullFeatures extends BootstrapFeatures {
|
|||||||
* Artifacts to use when deploying full features.
|
* Artifacts to use when deploying full features.
|
||||||
*/
|
*/
|
||||||
export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts {
|
export interface FullFeatureArtifacts extends BootstrapFeatureArtifacts {
|
||||||
tokenSpender: SimpleContractArtifact;
|
|
||||||
transformERC20: SimpleContractArtifact;
|
transformERC20: SimpleContractArtifact;
|
||||||
metaTransactions: SimpleContractArtifact;
|
metaTransactions: SimpleContractArtifact;
|
||||||
nativeOrders: SimpleContractArtifact;
|
nativeOrders: SimpleContractArtifact;
|
||||||
@ -133,7 +129,6 @@ export interface FullFeaturesDeployConfig {
|
|||||||
wethAddress: string;
|
wethAddress: string;
|
||||||
stakingAddress: string;
|
stakingAddress: string;
|
||||||
protocolFeeMultiplier: number;
|
protocolFeeMultiplier: number;
|
||||||
greedyTokensBloomFilter: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,11 +144,9 @@ const DEFAULT_FULL_FEATURES_DEPLOY_CONFIG = {
|
|||||||
stakingAddress: NULL_ADDRESS,
|
stakingAddress: NULL_ADDRESS,
|
||||||
feeCollectorController: NULL_ADDRESS,
|
feeCollectorController: NULL_ADDRESS,
|
||||||
protocolFeeMultiplier: 70e3,
|
protocolFeeMultiplier: 70e3,
|
||||||
greedyTokensBloomFilter: ZERO_BYTES32,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_FULL_FEATURES_ARTIFACTS = {
|
const DEFAULT_FULL_FEATURES_ARTIFACTS = {
|
||||||
tokenSpender: artifacts.TokenSpenderFeature,
|
|
||||||
transformERC20: artifacts.TransformERC20Feature,
|
transformERC20: artifacts.TransformERC20Feature,
|
||||||
metaTransactions: artifacts.MetaTransactionsFeature,
|
metaTransactions: artifacts.MetaTransactionsFeature,
|
||||||
nativeOrders: artifacts.NativeOrdersFeature,
|
nativeOrders: artifacts.NativeOrdersFeature,
|
||||||
@ -187,14 +180,6 @@ export async function deployFullFeaturesAsync(
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
|
...(await deployBootstrapFeaturesAsync(provider, txDefaults)),
|
||||||
tokenSpender:
|
|
||||||
features.tokenSpender ||
|
|
||||||
(await TokenSpenderFeatureContract.deployFrom0xArtifactAsync(
|
|
||||||
_featureArtifacts.tokenSpender,
|
|
||||||
provider,
|
|
||||||
txDefaults,
|
|
||||||
artifacts,
|
|
||||||
)).address,
|
|
||||||
transformERC20:
|
transformERC20:
|
||||||
features.transformERC20 ||
|
features.transformERC20 ||
|
||||||
(await TransformERC20FeatureContract.deployFrom0xArtifactAsync(
|
(await TransformERC20FeatureContract.deployFrom0xArtifactAsync(
|
||||||
@ -202,7 +187,6 @@ export async function deployFullFeaturesAsync(
|
|||||||
provider,
|
provider,
|
||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
_config.greedyTokensBloomFilter,
|
|
||||||
)).address,
|
)).address,
|
||||||
metaTransactions:
|
metaTransactions:
|
||||||
features.metaTransactions ||
|
features.metaTransactions ||
|
||||||
@ -212,7 +196,6 @@ export async function deployFullFeaturesAsync(
|
|||||||
txDefaults,
|
txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
_config.zeroExAddress,
|
_config.zeroExAddress,
|
||||||
_config.greedyTokensBloomFilter,
|
|
||||||
)).address,
|
)).address,
|
||||||
nativeOrders:
|
nativeOrders:
|
||||||
features.nativeOrders ||
|
features.nativeOrders ||
|
||||||
@ -226,7 +209,6 @@ export async function deployFullFeaturesAsync(
|
|||||||
_config.stakingAddress,
|
_config.stakingAddress,
|
||||||
_config.feeCollectorController,
|
_config.feeCollectorController,
|
||||||
_config.protocolFeeMultiplier,
|
_config.protocolFeeMultiplier,
|
||||||
_config.greedyTokensBloomFilter,
|
|
||||||
)).address,
|
)).address,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,6 @@ export * from '../generated-wrappers/i_multiplex_feature';
|
|||||||
export * from '../generated-wrappers/i_native_orders_feature';
|
export * from '../generated-wrappers/i_native_orders_feature';
|
||||||
export * from '../generated-wrappers/i_ownable_feature';
|
export * from '../generated-wrappers/i_ownable_feature';
|
||||||
export * from '../generated-wrappers/i_simple_function_registry_feature';
|
export * from '../generated-wrappers/i_simple_function_registry_feature';
|
||||||
export * from '../generated-wrappers/i_token_spender_feature';
|
|
||||||
export * from '../generated-wrappers/i_transform_erc20_feature';
|
export * from '../generated-wrappers/i_transform_erc20_feature';
|
||||||
export * from '../generated-wrappers/i_zero_ex';
|
export * from '../generated-wrappers/i_zero_ex';
|
||||||
export * from '../generated-wrappers/initial_migration';
|
export * from '../generated-wrappers/initial_migration';
|
||||||
@ -33,7 +32,6 @@ export * from '../generated-wrappers/ownable_feature';
|
|||||||
export * from '../generated-wrappers/pay_taker_transformer';
|
export * from '../generated-wrappers/pay_taker_transformer';
|
||||||
export * from '../generated-wrappers/positive_slippage_fee_transformer';
|
export * from '../generated-wrappers/positive_slippage_fee_transformer';
|
||||||
export * from '../generated-wrappers/simple_function_registry_feature';
|
export * from '../generated-wrappers/simple_function_registry_feature';
|
||||||
export * from '../generated-wrappers/token_spender_feature';
|
|
||||||
export * from '../generated-wrappers/transform_erc20_feature';
|
export * from '../generated-wrappers/transform_erc20_feature';
|
||||||
export * from '../generated-wrappers/weth_transformer';
|
export * from '../generated-wrappers/weth_transformer';
|
||||||
export * from '../generated-wrappers/zero_ex';
|
export * from '../generated-wrappers/zero_ex';
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
import { blockchainTests, constants, expect, randomAddress, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
|
||||||
import { AuthorizableRevertErrors, hexUtils, StringRevertError } from '@0x/utils';
|
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
|
||||||
import { AllowanceTargetContract, TestCallTargetContract, TestCallTargetEvents } from './wrappers';
|
|
||||||
|
|
||||||
blockchainTests.resets('AllowanceTarget', env => {
|
|
||||||
let owner: string;
|
|
||||||
let authority: string;
|
|
||||||
let allowanceTarget: AllowanceTargetContract;
|
|
||||||
let callTarget: TestCallTargetContract;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
[owner, authority] = await env.getAccountAddressesAsync();
|
|
||||||
allowanceTarget = await AllowanceTargetContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.AllowanceTarget,
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
await allowanceTarget.addAuthorizedAddress(authority).awaitTransactionSuccessAsync();
|
|
||||||
callTarget = await TestCallTargetContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.TestCallTarget,
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const TARGET_RETURN_VALUE = hexUtils.rightPad('0x12345678');
|
|
||||||
const REVERTING_DATA = '0x1337';
|
|
||||||
|
|
||||||
describe('executeCall()', () => {
|
|
||||||
it('non-authority cannot call executeCall()', async () => {
|
|
||||||
const notAuthority = randomAddress();
|
|
||||||
const tx = allowanceTarget
|
|
||||||
.executeCall(randomAddress(), hexUtils.random())
|
|
||||||
.callAsync({ from: notAuthority });
|
|
||||||
return expect(tx).to.revertWith(new AuthorizableRevertErrors.SenderNotAuthorizedError(notAuthority));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('authority can call executeCall()', async () => {
|
|
||||||
const targetData = hexUtils.random(128);
|
|
||||||
const receipt = await allowanceTarget
|
|
||||||
.executeCall(callTarget.address, targetData)
|
|
||||||
.awaitTransactionSuccessAsync({ from: authority });
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
context: callTarget.address,
|
|
||||||
sender: allowanceTarget.address,
|
|
||||||
data: targetData,
|
|
||||||
value: constants.ZERO_AMOUNT,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestCallTargetEvents.CallTargetCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('AllowanceTarget returns call result', async () => {
|
|
||||||
const result = await allowanceTarget
|
|
||||||
.executeCall(callTarget.address, hexUtils.random(128))
|
|
||||||
.callAsync({ from: authority });
|
|
||||||
expect(result).to.eq(TARGET_RETURN_VALUE);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('AllowanceTarget returns raw call revert', async () => {
|
|
||||||
const tx = allowanceTarget.executeCall(callTarget.address, REVERTING_DATA).callAsync({ from: authority });
|
|
||||||
return expect(tx).to.revertWith(new StringRevertError('TestCallTarget/REVERT'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('AllowanceTarget cannot receive ETH', async () => {
|
|
||||||
const tx = env.web3Wrapper.sendTransactionAsync({
|
|
||||||
to: allowanceTarget.address,
|
|
||||||
from: owner,
|
|
||||||
value: 0,
|
|
||||||
});
|
|
||||||
return expect(tx).to.eventually.be.rejected();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -6,11 +6,10 @@
|
|||||||
import { ContractArtifact } from 'ethereum-types';
|
import { ContractArtifact } from 'ethereum-types';
|
||||||
|
|
||||||
import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json';
|
import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json';
|
||||||
import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.json';
|
|
||||||
import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json';
|
import * as BatchFillNativeOrdersFeature from '../test/generated-artifacts/BatchFillNativeOrdersFeature.json';
|
||||||
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
|
import * as BootstrapFeature from '../test/generated-artifacts/BootstrapFeature.json';
|
||||||
import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json';
|
import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json';
|
||||||
import * as BridgeSource from '../test/generated-artifacts/BridgeSource.json';
|
import * as BridgeProtocols from '../test/generated-artifacts/BridgeProtocols.json';
|
||||||
import * as CurveLiquidityProvider from '../test/generated-artifacts/CurveLiquidityProvider.json';
|
import * as CurveLiquidityProvider from '../test/generated-artifacts/CurveLiquidityProvider.json';
|
||||||
import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json';
|
import * as FeeCollector from '../test/generated-artifacts/FeeCollector.json';
|
||||||
import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json';
|
import * as FeeCollectorController from '../test/generated-artifacts/FeeCollectorController.json';
|
||||||
@ -22,7 +21,6 @@ import * as FixinReentrancyGuard from '../test/generated-artifacts/FixinReentran
|
|||||||
import * as FixinTokenSpender from '../test/generated-artifacts/FixinTokenSpender.json';
|
import * as FixinTokenSpender from '../test/generated-artifacts/FixinTokenSpender.json';
|
||||||
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
|
import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json';
|
||||||
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
|
import * as FullMigration from '../test/generated-artifacts/FullMigration.json';
|
||||||
import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json';
|
|
||||||
import * as IBatchFillNativeOrdersFeature from '../test/generated-artifacts/IBatchFillNativeOrdersFeature.json';
|
import * as IBatchFillNativeOrdersFeature from '../test/generated-artifacts/IBatchFillNativeOrdersFeature.json';
|
||||||
import * as IBootstrapFeature from '../test/generated-artifacts/IBootstrapFeature.json';
|
import * as IBootstrapFeature from '../test/generated-artifacts/IBootstrapFeature.json';
|
||||||
import * as IBridgeAdapter from '../test/generated-artifacts/IBridgeAdapter.json';
|
import * as IBridgeAdapter from '../test/generated-artifacts/IBridgeAdapter.json';
|
||||||
@ -40,6 +38,7 @@ import * as INativeOrdersEvents from '../test/generated-artifacts/INativeOrdersE
|
|||||||
import * as INativeOrdersFeature from '../test/generated-artifacts/INativeOrdersFeature.json';
|
import * as INativeOrdersFeature from '../test/generated-artifacts/INativeOrdersFeature.json';
|
||||||
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
|
import * as InitialMigration from '../test/generated-artifacts/InitialMigration.json';
|
||||||
import * as IOwnableFeature from '../test/generated-artifacts/IOwnableFeature.json';
|
import * as IOwnableFeature from '../test/generated-artifacts/IOwnableFeature.json';
|
||||||
|
import * as IPancakeSwapFeature from '../test/generated-artifacts/IPancakeSwapFeature.json';
|
||||||
import * as ISimpleFunctionRegistryFeature from '../test/generated-artifacts/ISimpleFunctionRegistryFeature.json';
|
import * as ISimpleFunctionRegistryFeature from '../test/generated-artifacts/ISimpleFunctionRegistryFeature.json';
|
||||||
import * as IStaking from '../test/generated-artifacts/IStaking.json';
|
import * as IStaking from '../test/generated-artifacts/IStaking.json';
|
||||||
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
|
import * as ITestSimpleFunctionRegistryFeature from '../test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json';
|
||||||
@ -68,9 +67,7 @@ import * as LibSignature from '../test/generated-artifacts/LibSignature.json';
|
|||||||
import * as LibSignatureRichErrors from '../test/generated-artifacts/LibSignatureRichErrors.json';
|
import * as LibSignatureRichErrors from '../test/generated-artifacts/LibSignatureRichErrors.json';
|
||||||
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
|
import * as LibSimpleFunctionRegistryRichErrors from '../test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json';
|
||||||
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
|
import * as LibSimpleFunctionRegistryStorage from '../test/generated-artifacts/LibSimpleFunctionRegistryStorage.json';
|
||||||
import * as LibSpenderRichErrors from '../test/generated-artifacts/LibSpenderRichErrors.json';
|
|
||||||
import * as LibStorage from '../test/generated-artifacts/LibStorage.json';
|
import * as LibStorage from '../test/generated-artifacts/LibStorage.json';
|
||||||
import * as LibTokenSpenderStorage from '../test/generated-artifacts/LibTokenSpenderStorage.json';
|
|
||||||
import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTransformERC20RichErrors.json';
|
import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTransformERC20RichErrors.json';
|
||||||
import * as LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json';
|
import * as LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json';
|
||||||
import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json';
|
import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json';
|
||||||
@ -88,9 +85,9 @@ import * as MixinDodoV2 from '../test/generated-artifacts/MixinDodoV2.json';
|
|||||||
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
|
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
|
||||||
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
|
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
|
||||||
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
|
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
|
||||||
|
import * as MixinNerve from '../test/generated-artifacts/MixinNerve.json';
|
||||||
import * as MixinOasis from '../test/generated-artifacts/MixinOasis.json';
|
import * as MixinOasis from '../test/generated-artifacts/MixinOasis.json';
|
||||||
import * as MixinShell from '../test/generated-artifacts/MixinShell.json';
|
import * as MixinShell from '../test/generated-artifacts/MixinShell.json';
|
||||||
import * as MixinSushiswap from '../test/generated-artifacts/MixinSushiswap.json';
|
|
||||||
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
|
import * as MixinUniswap from '../test/generated-artifacts/MixinUniswap.json';
|
||||||
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
|
import * as MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
|
||||||
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
|
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
|
||||||
@ -102,6 +99,7 @@ import * as NativeOrdersInfo from '../test/generated-artifacts/NativeOrdersInfo.
|
|||||||
import * as NativeOrdersProtocolFees from '../test/generated-artifacts/NativeOrdersProtocolFees.json';
|
import * as NativeOrdersProtocolFees from '../test/generated-artifacts/NativeOrdersProtocolFees.json';
|
||||||
import * as NativeOrdersSettlement from '../test/generated-artifacts/NativeOrdersSettlement.json';
|
import * as NativeOrdersSettlement from '../test/generated-artifacts/NativeOrdersSettlement.json';
|
||||||
import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json';
|
import * as OwnableFeature from '../test/generated-artifacts/OwnableFeature.json';
|
||||||
|
import * as PancakeSwapFeature from '../test/generated-artifacts/PancakeSwapFeature.json';
|
||||||
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
|
import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json';
|
||||||
import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json';
|
import * as PermissionlessTransformerDeployer from '../test/generated-artifacts/PermissionlessTransformerDeployer.json';
|
||||||
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
|
import * as PositiveSlippageFeeTransformer from '../test/generated-artifacts/PositiveSlippageFeeTransformer.json';
|
||||||
@ -134,7 +132,6 @@ import * as TestRfqOriginRegistration from '../test/generated-artifacts/TestRfqO
|
|||||||
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
|
import * as TestSimpleFunctionRegistryFeatureImpl1 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json';
|
||||||
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
|
import * as TestSimpleFunctionRegistryFeatureImpl2 from '../test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json';
|
||||||
import * as TestStaking from '../test/generated-artifacts/TestStaking.json';
|
import * as TestStaking from '../test/generated-artifacts/TestStaking.json';
|
||||||
import * as TestTokenSpender from '../test/generated-artifacts/TestTokenSpender.json';
|
|
||||||
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
|
import * as TestTokenSpenderERC20Token from '../test/generated-artifacts/TestTokenSpenderERC20Token.json';
|
||||||
import * as TestTransformerBase from '../test/generated-artifacts/TestTransformerBase.json';
|
import * as TestTransformerBase from '../test/generated-artifacts/TestTransformerBase.json';
|
||||||
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
|
import * as TestTransformERC20 from '../test/generated-artifacts/TestTransformERC20.json';
|
||||||
@ -143,7 +140,6 @@ import * as TestTransformerHost from '../test/generated-artifacts/TestTransforme
|
|||||||
import * as TestWeth from '../test/generated-artifacts/TestWeth.json';
|
import * as TestWeth from '../test/generated-artifacts/TestWeth.json';
|
||||||
import * as TestWethTransformerHost from '../test/generated-artifacts/TestWethTransformerHost.json';
|
import * as TestWethTransformerHost from '../test/generated-artifacts/TestWethTransformerHost.json';
|
||||||
import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json';
|
import * as TestZeroExFeature from '../test/generated-artifacts/TestZeroExFeature.json';
|
||||||
import * as TokenSpenderFeature from '../test/generated-artifacts/TokenSpenderFeature.json';
|
|
||||||
import * as Transformer from '../test/generated-artifacts/Transformer.json';
|
import * as Transformer from '../test/generated-artifacts/Transformer.json';
|
||||||
import * as TransformERC20Feature from '../test/generated-artifacts/TransformERC20Feature.json';
|
import * as TransformERC20Feature from '../test/generated-artifacts/TransformERC20Feature.json';
|
||||||
import * as TransformerDeployer from '../test/generated-artifacts/TransformerDeployer.json';
|
import * as TransformerDeployer from '../test/generated-artifacts/TransformerDeployer.json';
|
||||||
@ -163,14 +159,11 @@ export const artifacts = {
|
|||||||
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
|
LibProxyRichErrors: LibProxyRichErrors as ContractArtifact,
|
||||||
LibSignatureRichErrors: LibSignatureRichErrors as ContractArtifact,
|
LibSignatureRichErrors: LibSignatureRichErrors as ContractArtifact,
|
||||||
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
|
LibSimpleFunctionRegistryRichErrors: LibSimpleFunctionRegistryRichErrors as ContractArtifact,
|
||||||
LibSpenderRichErrors: LibSpenderRichErrors as ContractArtifact,
|
|
||||||
LibTransformERC20RichErrors: LibTransformERC20RichErrors as ContractArtifact,
|
LibTransformERC20RichErrors: LibTransformERC20RichErrors as ContractArtifact,
|
||||||
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
|
LibWalletRichErrors: LibWalletRichErrors as ContractArtifact,
|
||||||
AllowanceTarget: AllowanceTarget as ContractArtifact,
|
|
||||||
FeeCollector: FeeCollector as ContractArtifact,
|
FeeCollector: FeeCollector as ContractArtifact,
|
||||||
FeeCollectorController: FeeCollectorController as ContractArtifact,
|
FeeCollectorController: FeeCollectorController as ContractArtifact,
|
||||||
FlashWallet: FlashWallet as ContractArtifact,
|
FlashWallet: FlashWallet as ContractArtifact,
|
||||||
IAllowanceTarget: IAllowanceTarget as ContractArtifact,
|
|
||||||
IFlashWallet: IFlashWallet as ContractArtifact,
|
IFlashWallet: IFlashWallet as ContractArtifact,
|
||||||
ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact,
|
ILiquidityProviderSandbox: ILiquidityProviderSandbox as ContractArtifact,
|
||||||
LibFeeCollector: LibFeeCollector as ContractArtifact,
|
LibFeeCollector: LibFeeCollector as ContractArtifact,
|
||||||
@ -184,8 +177,8 @@ export const artifacts = {
|
|||||||
MultiplexFeature: MultiplexFeature as ContractArtifact,
|
MultiplexFeature: MultiplexFeature as ContractArtifact,
|
||||||
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
|
NativeOrdersFeature: NativeOrdersFeature as ContractArtifact,
|
||||||
OwnableFeature: OwnableFeature as ContractArtifact,
|
OwnableFeature: OwnableFeature as ContractArtifact,
|
||||||
|
PancakeSwapFeature: PancakeSwapFeature as ContractArtifact,
|
||||||
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
|
SimpleFunctionRegistryFeature: SimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
TokenSpenderFeature: TokenSpenderFeature as ContractArtifact,
|
|
||||||
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
|
TransformERC20Feature: TransformERC20Feature as ContractArtifact,
|
||||||
UniswapFeature: UniswapFeature as ContractArtifact,
|
UniswapFeature: UniswapFeature as ContractArtifact,
|
||||||
IBatchFillNativeOrdersFeature: IBatchFillNativeOrdersFeature as ContractArtifact,
|
IBatchFillNativeOrdersFeature: IBatchFillNativeOrdersFeature as ContractArtifact,
|
||||||
@ -197,6 +190,7 @@ export const artifacts = {
|
|||||||
INativeOrdersEvents: INativeOrdersEvents as ContractArtifact,
|
INativeOrdersEvents: INativeOrdersEvents as ContractArtifact,
|
||||||
INativeOrdersFeature: INativeOrdersFeature as ContractArtifact,
|
INativeOrdersFeature: INativeOrdersFeature as ContractArtifact,
|
||||||
IOwnableFeature: IOwnableFeature as ContractArtifact,
|
IOwnableFeature: IOwnableFeature as ContractArtifact,
|
||||||
|
IPancakeSwapFeature: IPancakeSwapFeature as ContractArtifact,
|
||||||
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
|
ISimpleFunctionRegistryFeature: ISimpleFunctionRegistryFeature as ContractArtifact,
|
||||||
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
|
ITokenSpenderFeature: ITokenSpenderFeature as ContractArtifact,
|
||||||
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
|
ITransformERC20Feature: ITransformERC20Feature as ContractArtifact,
|
||||||
@ -225,7 +219,6 @@ export const artifacts = {
|
|||||||
LibReentrancyGuardStorage: LibReentrancyGuardStorage as ContractArtifact,
|
LibReentrancyGuardStorage: LibReentrancyGuardStorage as ContractArtifact,
|
||||||
LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact,
|
LibSimpleFunctionRegistryStorage: LibSimpleFunctionRegistryStorage as ContractArtifact,
|
||||||
LibStorage: LibStorage as ContractArtifact,
|
LibStorage: LibStorage as ContractArtifact,
|
||||||
LibTokenSpenderStorage: LibTokenSpenderStorage as ContractArtifact,
|
|
||||||
LibTransformERC20Storage: LibTransformERC20Storage as ContractArtifact,
|
LibTransformERC20Storage: LibTransformERC20Storage as ContractArtifact,
|
||||||
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
|
AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact,
|
||||||
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
|
FillQuoteTransformer: FillQuoteTransformer as ContractArtifact,
|
||||||
@ -237,7 +230,7 @@ export const artifacts = {
|
|||||||
Transformer: Transformer as ContractArtifact,
|
Transformer: Transformer as ContractArtifact,
|
||||||
WethTransformer: WethTransformer as ContractArtifact,
|
WethTransformer: WethTransformer as ContractArtifact,
|
||||||
BridgeAdapter: BridgeAdapter as ContractArtifact,
|
BridgeAdapter: BridgeAdapter as ContractArtifact,
|
||||||
BridgeSource: BridgeSource as ContractArtifact,
|
BridgeProtocols: BridgeProtocols as ContractArtifact,
|
||||||
IBridgeAdapter: IBridgeAdapter as ContractArtifact,
|
IBridgeAdapter: IBridgeAdapter as ContractArtifact,
|
||||||
MixinBalancer: MixinBalancer as ContractArtifact,
|
MixinBalancer: MixinBalancer as ContractArtifact,
|
||||||
MixinBancor: MixinBancor as ContractArtifact,
|
MixinBancor: MixinBancor as ContractArtifact,
|
||||||
@ -249,9 +242,9 @@ export const artifacts = {
|
|||||||
MixinKyber: MixinKyber as ContractArtifact,
|
MixinKyber: MixinKyber as ContractArtifact,
|
||||||
MixinMStable: MixinMStable as ContractArtifact,
|
MixinMStable: MixinMStable as ContractArtifact,
|
||||||
MixinMooniswap: MixinMooniswap as ContractArtifact,
|
MixinMooniswap: MixinMooniswap as ContractArtifact,
|
||||||
|
MixinNerve: MixinNerve as ContractArtifact,
|
||||||
MixinOasis: MixinOasis as ContractArtifact,
|
MixinOasis: MixinOasis as ContractArtifact,
|
||||||
MixinShell: MixinShell as ContractArtifact,
|
MixinShell: MixinShell as ContractArtifact,
|
||||||
MixinSushiswap: MixinSushiswap as ContractArtifact,
|
|
||||||
MixinUniswap: MixinUniswap as ContractArtifact,
|
MixinUniswap: MixinUniswap as ContractArtifact,
|
||||||
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
|
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
|
||||||
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
|
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,
|
||||||
@ -289,7 +282,6 @@ export const artifacts = {
|
|||||||
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
|
TestSimpleFunctionRegistryFeatureImpl1: TestSimpleFunctionRegistryFeatureImpl1 as ContractArtifact,
|
||||||
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
|
TestSimpleFunctionRegistryFeatureImpl2: TestSimpleFunctionRegistryFeatureImpl2 as ContractArtifact,
|
||||||
TestStaking: TestStaking as ContractArtifact,
|
TestStaking: TestStaking as ContractArtifact,
|
||||||
TestTokenSpender: TestTokenSpender as ContractArtifact,
|
|
||||||
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
|
TestTokenSpenderERC20Token: TestTokenSpenderERC20Token as ContractArtifact,
|
||||||
TestTransformERC20: TestTransformERC20 as ContractArtifact,
|
TestTransformERC20: TestTransformERC20 as ContractArtifact,
|
||||||
TestTransformerBase: TestTransformerBase as ContractArtifact,
|
TestTransformerBase: TestTransformerBase as ContractArtifact,
|
||||||
|
@ -2,7 +2,6 @@ import { artifacts as erc20Artifacts, DummyERC20TokenContract } from '@0x/contra
|
|||||||
import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
import { blockchainTests, constants, expect, verifyEventsFromLogs } from '@0x/contracts-test-utils';
|
||||||
import { BigNumber, OwnableRevertErrors, ZeroExRevertErrors } from '@0x/utils';
|
import { BigNumber, OwnableRevertErrors, ZeroExRevertErrors } from '@0x/utils';
|
||||||
|
|
||||||
import { ZERO_BYTES32 } from '../../src/constants';
|
|
||||||
import { IOwnableFeatureContract, IZeroExContract, LiquidityProviderFeatureContract } from '../../src/wrappers';
|
import { IOwnableFeatureContract, IZeroExContract, LiquidityProviderFeatureContract } from '../../src/wrappers';
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import { abis } from '../utils/abis';
|
import { abis } from '../utils/abis';
|
||||||
@ -63,7 +62,6 @@ blockchainTests('LiquidityProvider feature', env => {
|
|||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
sandbox.address,
|
sandbox.address,
|
||||||
ZERO_BYTES32,
|
|
||||||
);
|
);
|
||||||
await new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis)
|
await new IOwnableFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis)
|
||||||
.migrate(featureImpl.address, featureImpl.migrate().getABIEncodedTransactionData(), owner)
|
.migrate(featureImpl.address, featureImpl.migrate().getABIEncodedTransactionData(), owner)
|
||||||
|
@ -8,7 +8,8 @@ import {
|
|||||||
} from '@0x/contracts-erc20';
|
} from '@0x/contracts-erc20';
|
||||||
import { blockchainTests, constants, expect, filterLogsToArguments, toBaseUnitAmount } from '@0x/contracts-test-utils';
|
import { blockchainTests, constants, expect, filterLogsToArguments, toBaseUnitAmount } from '@0x/contracts-test-utils';
|
||||||
import {
|
import {
|
||||||
BridgeSource,
|
BridgeProtocol,
|
||||||
|
encodeBridgeSourceId,
|
||||||
encodeFillQuoteTransformerData,
|
encodeFillQuoteTransformerData,
|
||||||
encodePayTakerTransformerData,
|
encodePayTakerTransformerData,
|
||||||
FillQuoteTransformerOrderType,
|
FillQuoteTransformerOrderType,
|
||||||
@ -72,8 +73,9 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
const WETH_DAI_PLP_ADDRESS = '0x1db681925786441ba82adefac7bf492089665ca0';
|
const WETH_DAI_PLP_ADDRESS = '0x1db681925786441ba82adefac7bf492089665ca0';
|
||||||
const WETH_USDC_PLP_ADDRESS = '0x8463c03c0c57ff19fa8b431e0d3a34e2df89888e';
|
const WETH_USDC_PLP_ADDRESS = '0x8463c03c0c57ff19fa8b431e0d3a34e2df89888e';
|
||||||
const USDC_USDT_PLP_ADDRESS = '0xc340ef96449514cea4dfa11d847a06d7f03d437c';
|
const USDC_USDT_PLP_ADDRESS = '0xc340ef96449514cea4dfa11d847a06d7f03d437c';
|
||||||
const GREEDY_TOKENS_BLOOM_FILTER = '0x0000100800000480002c00401000000820000000000000020000001010800001';
|
|
||||||
const BALANCER_WETH_DAI = '0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a';
|
const BALANCER_WETH_DAI = '0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a';
|
||||||
|
const CURVE_BRIDGE_SOURCE_ID = encodeBridgeSourceId(BridgeProtocol.Curve, 'Curve');
|
||||||
|
const BALANCER_BRIDGE_SOURCE_ID = encodeBridgeSourceId(BridgeProtocol.Bancor, 'Balancer');
|
||||||
const fqtNonce = findTransformerNonce(
|
const fqtNonce = findTransformerNonce(
|
||||||
'0xfa6282736af206cb4cfc5cb786d82aecdf1186f9',
|
'0xfa6282736af206cb4cfc5cb786d82aecdf1186f9',
|
||||||
'0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb',
|
'0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb',
|
||||||
@ -112,7 +114,6 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
zeroEx.address,
|
zeroEx.address,
|
||||||
WETH_ADDRESS,
|
WETH_ADDRESS,
|
||||||
PLP_SANDBOX_ADDRESS,
|
PLP_SANDBOX_ADDRESS,
|
||||||
GREEDY_TOKENS_BLOOM_FILTER,
|
|
||||||
);
|
);
|
||||||
await registry
|
await registry
|
||||||
.extend(multiplex.getSelector('batchFill'), multiplexImpl.address)
|
.extend(multiplex.getSelector('batchFill'), multiplexImpl.address)
|
||||||
@ -283,7 +284,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
buyToken: WETH_ADDRESS,
|
buyToken: WETH_ADDRESS,
|
||||||
bridgeOrders: [
|
bridgeOrders: [
|
||||||
{
|
{
|
||||||
source: BridgeSource.Balancer,
|
source: BALANCER_BRIDGE_SOURCE_ID,
|
||||||
takerTokenAmount: expiredRfqCall.sellAmount,
|
takerTokenAmount: expiredRfqCall.sellAmount,
|
||||||
makerTokenAmount: expiredRfqCall.sellAmount,
|
makerTokenAmount: expiredRfqCall.sellAmount,
|
||||||
bridgeData: poolEncoder.encode([BALANCER_WETH_DAI]),
|
bridgeData: poolEncoder.encode([BALANCER_WETH_DAI]),
|
||||||
@ -339,7 +340,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
tx.logs,
|
tx.logs,
|
||||||
BridgeAdapterEvents.BridgeFill,
|
BridgeAdapterEvents.BridgeFill,
|
||||||
);
|
);
|
||||||
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Balancer);
|
expect(bridgeFillEvent.source).to.bignumber.equal(BALANCER_BRIDGE_SOURCE_ID);
|
||||||
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
|
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
|
||||||
expect(bridgeFillEvent.outputToken).to.equal(WETH_ADDRESS);
|
expect(bridgeFillEvent.outputToken).to.equal(WETH_ADDRESS);
|
||||||
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(expiredRfqCall.sellAmount);
|
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(expiredRfqCall.sellAmount);
|
||||||
@ -472,7 +473,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
buyToken: USDC_ADDRESS,
|
buyToken: USDC_ADDRESS,
|
||||||
bridgeOrders: [
|
bridgeOrders: [
|
||||||
{
|
{
|
||||||
source: BridgeSource.Curve,
|
source: CURVE_BRIDGE_SOURCE_ID,
|
||||||
takerTokenAmount: sellAmount,
|
takerTokenAmount: sellAmount,
|
||||||
makerTokenAmount: sellAmount,
|
makerTokenAmount: sellAmount,
|
||||||
bridgeData: curveEncoder.encode([
|
bridgeData: curveEncoder.encode([
|
||||||
@ -531,7 +532,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
tx.logs,
|
tx.logs,
|
||||||
BridgeAdapterEvents.BridgeFill,
|
BridgeAdapterEvents.BridgeFill,
|
||||||
);
|
);
|
||||||
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Curve);
|
expect(bridgeFillEvent.source).to.bignumber.equal(CURVE_BRIDGE_SOURCE_ID);
|
||||||
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
|
expect(bridgeFillEvent.inputToken).to.equal(DAI_ADDRESS);
|
||||||
expect(bridgeFillEvent.outputToken).to.equal(USDC_ADDRESS);
|
expect(bridgeFillEvent.outputToken).to.equal(USDC_ADDRESS);
|
||||||
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(sellAmount);
|
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(sellAmount);
|
||||||
@ -563,7 +564,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
buyToken: DAI_ADDRESS,
|
buyToken: DAI_ADDRESS,
|
||||||
bridgeOrders: [
|
bridgeOrders: [
|
||||||
{
|
{
|
||||||
source: BridgeSource.Curve,
|
source: CURVE_BRIDGE_SOURCE_ID,
|
||||||
takerTokenAmount: constants.MAX_UINT256,
|
takerTokenAmount: constants.MAX_UINT256,
|
||||||
makerTokenAmount: constants.MAX_UINT256,
|
makerTokenAmount: constants.MAX_UINT256,
|
||||||
bridgeData: curveEncoder.encode([
|
bridgeData: curveEncoder.encode([
|
||||||
@ -640,7 +641,7 @@ blockchainTests.fork.skip('Multiplex feature', env => {
|
|||||||
tx.logs,
|
tx.logs,
|
||||||
BridgeAdapterEvents.BridgeFill,
|
BridgeAdapterEvents.BridgeFill,
|
||||||
);
|
);
|
||||||
expect(bridgeFillEvent.source).to.bignumber.equal(BridgeSource.Curve);
|
expect(bridgeFillEvent.source).to.bignumber.equal(CURVE_BRIDGE_SOURCE_ID);
|
||||||
expect(bridgeFillEvent.inputToken).to.equal(USDC_ADDRESS);
|
expect(bridgeFillEvent.inputToken).to.equal(USDC_ADDRESS);
|
||||||
expect(bridgeFillEvent.outputToken).to.equal(DAI_ADDRESS);
|
expect(bridgeFillEvent.outputToken).to.equal(DAI_ADDRESS);
|
||||||
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(uniswapOutputAmount);
|
expect(bridgeFillEvent.inputTokenAmount).to.bignumber.equal(uniswapOutputAmount);
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
import {
|
|
||||||
blockchainTests,
|
|
||||||
expect,
|
|
||||||
getRandomInteger,
|
|
||||||
randomAddress,
|
|
||||||
verifyEventsFromLogs,
|
|
||||||
} from '@0x/contracts-test-utils';
|
|
||||||
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
|
||||||
|
|
||||||
import { IZeroExContract, TokenSpenderFeatureContract } from '../../src/wrappers';
|
|
||||||
import { artifacts } from '../artifacts';
|
|
||||||
import { abis } from '../utils/abis';
|
|
||||||
import { fullMigrateAsync } from '../utils/migration';
|
|
||||||
import { TestTokenSpenderERC20TokenContract, TestTokenSpenderERC20TokenEvents } from '../wrappers';
|
|
||||||
|
|
||||||
blockchainTests.resets('TokenSpender feature', env => {
|
|
||||||
let zeroEx: IZeroExContract;
|
|
||||||
let feature: TokenSpenderFeatureContract;
|
|
||||||
let token: TestTokenSpenderERC20TokenContract;
|
|
||||||
let allowanceTarget: string;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
const [owner] = await env.getAccountAddressesAsync();
|
|
||||||
zeroEx = await fullMigrateAsync(owner, env.provider, env.txDefaults, {
|
|
||||||
tokenSpender: (await TokenSpenderFeatureContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.TestTokenSpender,
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
artifacts,
|
|
||||||
)).address,
|
|
||||||
});
|
|
||||||
feature = new TokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults, abis);
|
|
||||||
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
|
|
||||||
artifacts.TestTokenSpenderERC20Token,
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
artifacts,
|
|
||||||
);
|
|
||||||
allowanceTarget = await feature.getAllowanceTarget().callAsync();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('_spendERC20Tokens()', () => {
|
|
||||||
const EMPTY_RETURN_AMOUNT = 1337;
|
|
||||||
const FALSE_RETURN_AMOUNT = 1338;
|
|
||||||
const REVERT_RETURN_AMOUNT = 1339;
|
|
||||||
|
|
||||||
it('_spendERC20Tokens() successfully calls compliant ERC20 token', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(123456);
|
|
||||||
const receipt = await feature
|
|
||||||
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
sender: allowanceTarget,
|
|
||||||
from: tokenFrom,
|
|
||||||
to: tokenTo,
|
|
||||||
amount: tokenAmount,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('_spendERC20Tokens() successfully calls non-compliant ERC20 token', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(EMPTY_RETURN_AMOUNT);
|
|
||||||
const receipt = await feature
|
|
||||||
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
sender: allowanceTarget,
|
|
||||||
from: tokenFrom,
|
|
||||||
to: tokenTo,
|
|
||||||
amount: tokenAmount,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('_spendERC20Tokens() reverts if ERC20 token reverts', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(REVERT_RETURN_AMOUNT);
|
|
||||||
const tx = feature
|
|
||||||
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
const expectedError = new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
|
||||||
token.address,
|
|
||||||
tokenFrom,
|
|
||||||
tokenTo,
|
|
||||||
tokenAmount,
|
|
||||||
new StringRevertError('TestTokenSpenderERC20Token/Revert').encode(),
|
|
||||||
);
|
|
||||||
return expect(tx).to.revertWith(expectedError);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('_spendERC20Tokens() reverts if ERC20 token returns false', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(FALSE_RETURN_AMOUNT);
|
|
||||||
const tx = feature
|
|
||||||
._spendERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
return expect(tx).to.revertWith(
|
|
||||||
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
|
||||||
token.address,
|
|
||||||
tokenFrom,
|
|
||||||
tokenTo,
|
|
||||||
tokenAmount,
|
|
||||||
hexUtils.leftPad(0),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getSpendableERC20BalanceOf()', () => {
|
|
||||||
it("returns the minimum of the owner's balance and allowance", async () => {
|
|
||||||
const balance = getRandomInteger(1, '1e18');
|
|
||||||
const allowance = getRandomInteger(1, '1e18');
|
|
||||||
const tokenOwner = randomAddress();
|
|
||||||
await token
|
|
||||||
.setBalanceAndAllowanceOf(tokenOwner, balance, allowanceTarget, allowance)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
const spendableBalance = await feature.getSpendableERC20BalanceOf(token.address, tokenOwner).callAsync();
|
|
||||||
expect(spendableBalance).to.bignumber.eq(BigNumber.min(balance, allowance));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -5,14 +5,11 @@ import {
|
|||||||
randomAddress,
|
randomAddress,
|
||||||
verifyEventsFromLogs,
|
verifyEventsFromLogs,
|
||||||
} from '@0x/contracts-test-utils';
|
} from '@0x/contracts-test-utils';
|
||||||
import { BigNumber, hexUtils, StringRevertError, ZeroExRevertErrors } from '@0x/utils';
|
import { BigNumber, hexUtils, RawRevertError, StringRevertError } from '@0x/utils';
|
||||||
|
|
||||||
import { getTokenListBloomFilter } from '../src/bloom_filter_utils';
|
|
||||||
|
|
||||||
import { artifacts } from './artifacts';
|
import { artifacts } from './artifacts';
|
||||||
import {
|
import {
|
||||||
TestFixinTokenSpenderContract,
|
TestFixinTokenSpenderContract,
|
||||||
TestFixinTokenSpenderEvents,
|
|
||||||
TestTokenSpenderERC20TokenContract,
|
TestTokenSpenderERC20TokenContract,
|
||||||
TestTokenSpenderERC20TokenEvents,
|
TestTokenSpenderERC20TokenEvents,
|
||||||
} from './wrappers';
|
} from './wrappers';
|
||||||
@ -21,7 +18,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
let tokenSpender: TestFixinTokenSpenderContract;
|
let tokenSpender: TestFixinTokenSpenderContract;
|
||||||
let token: TestTokenSpenderERC20TokenContract;
|
let token: TestTokenSpenderERC20TokenContract;
|
||||||
let greedyToken: TestTokenSpenderERC20TokenContract;
|
let greedyToken: TestTokenSpenderERC20TokenContract;
|
||||||
let greedyTokensBloomFilter: string;
|
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
|
token = await TestTokenSpenderERC20TokenContract.deployFrom0xArtifactAsync(
|
||||||
@ -38,14 +34,11 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
);
|
);
|
||||||
await greedyToken.setGreedyRevert(true).awaitTransactionSuccessAsync();
|
await greedyToken.setGreedyRevert(true).awaitTransactionSuccessAsync();
|
||||||
|
|
||||||
greedyTokensBloomFilter = getTokenListBloomFilter([greedyToken.address]);
|
|
||||||
|
|
||||||
tokenSpender = await TestFixinTokenSpenderContract.deployFrom0xArtifactAsync(
|
tokenSpender = await TestFixinTokenSpenderContract.deployFrom0xArtifactAsync(
|
||||||
artifacts.TestFixinTokenSpender,
|
artifacts.TestFixinTokenSpender,
|
||||||
env.provider,
|
env.provider,
|
||||||
env.txDefaults,
|
env.txDefaults,
|
||||||
artifacts,
|
artifacts,
|
||||||
greedyTokensBloomFilter,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -53,7 +46,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
const EMPTY_RETURN_AMOUNT = 1337;
|
const EMPTY_RETURN_AMOUNT = 1337;
|
||||||
const FALSE_RETURN_AMOUNT = 1338;
|
const FALSE_RETURN_AMOUNT = 1338;
|
||||||
const REVERT_RETURN_AMOUNT = 1339;
|
const REVERT_RETURN_AMOUNT = 1339;
|
||||||
const TRIGGER_FALLBACK_SUCCESS_AMOUNT = 1340;
|
|
||||||
const EXTRA_RETURN_TRUE_AMOUNT = 1341;
|
const EXTRA_RETURN_TRUE_AMOUNT = 1341;
|
||||||
const EXTRA_RETURN_FALSE_AMOUNT = 1342;
|
const EXTRA_RETURN_FALSE_AMOUNT = 1342;
|
||||||
|
|
||||||
@ -106,13 +98,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
const tx = tokenSpender
|
const tx = tokenSpender
|
||||||
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
.awaitTransactionSuccessAsync();
|
.awaitTransactionSuccessAsync();
|
||||||
const expectedError = new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
const expectedError = new StringRevertError('TestTokenSpenderERC20Token/Revert');
|
||||||
token.address,
|
|
||||||
tokenFrom,
|
|
||||||
tokenTo,
|
|
||||||
tokenAmount,
|
|
||||||
new StringRevertError('TestTokenSpenderERC20Token/Revert').encode(),
|
|
||||||
);
|
|
||||||
return expect(tx).to.revertWith(expectedError);
|
return expect(tx).to.revertWith(expectedError);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -123,36 +109,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
const tx = tokenSpender
|
const tx = tokenSpender
|
||||||
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
.awaitTransactionSuccessAsync();
|
.awaitTransactionSuccessAsync();
|
||||||
return expect(tx).to.revertWith(
|
return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(0)));
|
||||||
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
|
||||||
token.address,
|
|
||||||
tokenFrom,
|
|
||||||
tokenTo,
|
|
||||||
tokenAmount,
|
|
||||||
hexUtils.leftPad(0),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('transferERC20Tokens() falls back successfully to TokenSpender._spendERC20Tokens()', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(TRIGGER_FALLBACK_SUCCESS_AMOUNT);
|
|
||||||
const receipt = await tokenSpender
|
|
||||||
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
token: token.address,
|
|
||||||
owner: tokenFrom,
|
|
||||||
to: tokenTo,
|
|
||||||
amount: tokenAmount,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestFixinTokenSpenderEvents.FallbackCalled,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('transferERC20Tokens() allows extra data after true', async () => {
|
it('transferERC20Tokens() allows extra data after true', async () => {
|
||||||
@ -185,15 +142,7 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
const tx = tokenSpender
|
const tx = tokenSpender
|
||||||
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
.transferERC20Tokens(token.address, tokenFrom, tokenTo, tokenAmount)
|
||||||
.awaitTransactionSuccessAsync();
|
.awaitTransactionSuccessAsync();
|
||||||
return expect(tx).to.revertWith(
|
return expect(tx).to.revertWith(new RawRevertError(hexUtils.leftPad(EXTRA_RETURN_FALSE_AMOUNT, 64)));
|
||||||
new ZeroExRevertErrors.Spender.SpenderERC20TransferFromFailedError(
|
|
||||||
token.address,
|
|
||||||
tokenFrom,
|
|
||||||
tokenTo,
|
|
||||||
tokenAmount,
|
|
||||||
hexUtils.leftPad(EXTRA_RETURN_FALSE_AMOUNT, 64),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('transferERC20Tokens() cannot call self', async () => {
|
it('transferERC20Tokens() cannot call self', async () => {
|
||||||
@ -206,73 +155,6 @@ blockchainTests.resets('FixinTokenSpender', env => {
|
|||||||
.awaitTransactionSuccessAsync();
|
.awaitTransactionSuccessAsync();
|
||||||
return expect(tx).to.revertWith('FixinTokenSpender/CANNOT_INVOKE_SELF');
|
return expect(tx).to.revertWith('FixinTokenSpender/CANNOT_INVOKE_SELF');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls transferFrom() directly for a greedy token with allowance', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(123456);
|
|
||||||
await greedyToken.approveAs(tokenFrom, tokenSpender.address, tokenAmount).awaitTransactionSuccessAsync();
|
|
||||||
|
|
||||||
const receipt = await tokenSpender
|
|
||||||
.transferERC20Tokens(greedyToken.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
// Because there is an allowance set, we will call transferFrom()
|
|
||||||
// directly, which succeds and emits an event.
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
sender: tokenSpender.address,
|
|
||||||
from: tokenFrom,
|
|
||||||
to: tokenTo,
|
|
||||||
amount: tokenAmount,
|
|
||||||
},
|
|
||||||
], // No events.
|
|
||||||
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('calls only the fallback for a greedy token with no allowance', async () => {
|
|
||||||
const tokenFrom = randomAddress();
|
|
||||||
const tokenTo = randomAddress();
|
|
||||||
const tokenAmount = new BigNumber(TRIGGER_FALLBACK_SUCCESS_AMOUNT);
|
|
||||||
|
|
||||||
const receipt = await tokenSpender
|
|
||||||
.transferERC20Tokens(greedyToken.address, tokenFrom, tokenTo, tokenAmount)
|
|
||||||
.awaitTransactionSuccessAsync();
|
|
||||||
// Because this is a greedy token and there is no allowance set, transferFrom()
|
|
||||||
// will not be called before hitting the fallback, which only emits an event
|
|
||||||
// in the test contract.
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[], // No events.
|
|
||||||
TestTokenSpenderERC20TokenEvents.TransferFromCalled,
|
|
||||||
);
|
|
||||||
verifyEventsFromLogs(
|
|
||||||
receipt.logs,
|
|
||||||
[
|
|
||||||
{
|
|
||||||
token: greedyToken.address,
|
|
||||||
owner: tokenFrom,
|
|
||||||
to: tokenTo,
|
|
||||||
amount: tokenAmount,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
TestFixinTokenSpenderEvents.FallbackCalled,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('isTokenPossiblyGreedy()', () => {
|
|
||||||
it('returns true for greedy token', async () => {
|
|
||||||
const isGreedy = await tokenSpender.isTokenPossiblyGreedy(greedyToken.address).callAsync();
|
|
||||||
expect(isGreedy).to.eq(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns false for non-greedy token', async () => {
|
|
||||||
const isGreedy = await tokenSpender.isTokenPossiblyGreedy(token.address).callAsync();
|
|
||||||
expect(isGreedy).to.eq(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getSpendableERC20BalanceOf()', () => {
|
describe('getSpendableERC20BalanceOf()', () => {
|
||||||
|
@ -8,11 +8,9 @@ import { artifacts } from './artifacts';
|
|||||||
import { abis } from './utils/abis';
|
import { abis } from './utils/abis';
|
||||||
import { deployFullFeaturesAsync, FullFeatures } from './utils/migration';
|
import { deployFullFeaturesAsync, FullFeatures } from './utils/migration';
|
||||||
import {
|
import {
|
||||||
AllowanceTargetContract,
|
|
||||||
IMetaTransactionsFeatureContract,
|
IMetaTransactionsFeatureContract,
|
||||||
INativeOrdersFeatureContract,
|
INativeOrdersFeatureContract,
|
||||||
IOwnableFeatureContract,
|
IOwnableFeatureContract,
|
||||||
ITokenSpenderFeatureContract,
|
|
||||||
ITransformERC20FeatureContract,
|
ITransformERC20FeatureContract,
|
||||||
TestFullMigrationContract,
|
TestFullMigrationContract,
|
||||||
ZeroExContract,
|
ZeroExContract,
|
||||||
@ -69,10 +67,6 @@ blockchainTests.resets('Full migration', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const FEATURE_FNS = {
|
const FEATURE_FNS = {
|
||||||
TokenSpender: {
|
|
||||||
contractType: ITokenSpenderFeatureContract,
|
|
||||||
fns: ['_spendERC20Tokens'],
|
|
||||||
},
|
|
||||||
TransformERC20: {
|
TransformERC20: {
|
||||||
contractType: ITransformERC20FeatureContract,
|
contractType: ITransformERC20FeatureContract,
|
||||||
fns: [
|
fns: [
|
||||||
@ -207,27 +201,6 @@ blockchainTests.resets('Full migration', env => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("TokenSpender's allowance target", () => {
|
|
||||||
let allowanceTarget: AllowanceTargetContract;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
const contract = new ITokenSpenderFeatureContract(zeroEx.address, env.provider, env.txDefaults);
|
|
||||||
allowanceTarget = new AllowanceTargetContract(
|
|
||||||
await contract.getAllowanceTarget().callAsync(),
|
|
||||||
env.provider,
|
|
||||||
env.txDefaults,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('is owned by owner', async () => {
|
|
||||||
return expect(allowanceTarget.owner().callAsync()).to.become(owner);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Proxy is authorized', async () => {
|
|
||||||
return expect(allowanceTarget.authorized(zeroEx.address).callAsync()).to.become(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('TransformERC20', () => {
|
describe('TransformERC20', () => {
|
||||||
let feature: ITransformERC20FeatureContract;
|
let feature: ITransformERC20FeatureContract;
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ blockchainTests.resets('FillQuoteTransformer', env => {
|
|||||||
let singleProtocolFee: BigNumber;
|
let singleProtocolFee: BigNumber;
|
||||||
|
|
||||||
const GAS_PRICE = 1337;
|
const GAS_PRICE = 1337;
|
||||||
const TEST_BRIDGE_SOURCE = 12345678;
|
const TEST_BRIDGE_SOURCE = hexUtils.random(32);
|
||||||
const HIGH_BIT = new BigNumber(2).pow(255);
|
const HIGH_BIT = new BigNumber(2).pow(255);
|
||||||
const REVERT_AMOUNT = new BigNumber('0xdeadbeef');
|
const REVERT_AMOUNT = new BigNumber('0xdeadbeef');
|
||||||
|
|
||||||
|
@ -4,11 +4,10 @@
|
|||||||
* -----------------------------------------------------------------------------
|
* -----------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
export * from '../test/generated-wrappers/affiliate_fee_transformer';
|
export * from '../test/generated-wrappers/affiliate_fee_transformer';
|
||||||
export * from '../test/generated-wrappers/allowance_target';
|
|
||||||
export * from '../test/generated-wrappers/batch_fill_native_orders_feature';
|
export * from '../test/generated-wrappers/batch_fill_native_orders_feature';
|
||||||
export * from '../test/generated-wrappers/bootstrap_feature';
|
export * from '../test/generated-wrappers/bootstrap_feature';
|
||||||
export * from '../test/generated-wrappers/bridge_adapter';
|
export * from '../test/generated-wrappers/bridge_adapter';
|
||||||
export * from '../test/generated-wrappers/bridge_source';
|
export * from '../test/generated-wrappers/bridge_protocols';
|
||||||
export * from '../test/generated-wrappers/curve_liquidity_provider';
|
export * from '../test/generated-wrappers/curve_liquidity_provider';
|
||||||
export * from '../test/generated-wrappers/fee_collector';
|
export * from '../test/generated-wrappers/fee_collector';
|
||||||
export * from '../test/generated-wrappers/fee_collector_controller';
|
export * from '../test/generated-wrappers/fee_collector_controller';
|
||||||
@ -20,7 +19,6 @@ export * from '../test/generated-wrappers/fixin_reentrancy_guard';
|
|||||||
export * from '../test/generated-wrappers/fixin_token_spender';
|
export * from '../test/generated-wrappers/fixin_token_spender';
|
||||||
export * from '../test/generated-wrappers/flash_wallet';
|
export * from '../test/generated-wrappers/flash_wallet';
|
||||||
export * from '../test/generated-wrappers/full_migration';
|
export * from '../test/generated-wrappers/full_migration';
|
||||||
export * from '../test/generated-wrappers/i_allowance_target';
|
|
||||||
export * from '../test/generated-wrappers/i_batch_fill_native_orders_feature';
|
export * from '../test/generated-wrappers/i_batch_fill_native_orders_feature';
|
||||||
export * from '../test/generated-wrappers/i_bootstrap_feature';
|
export * from '../test/generated-wrappers/i_bootstrap_feature';
|
||||||
export * from '../test/generated-wrappers/i_bridge_adapter';
|
export * from '../test/generated-wrappers/i_bridge_adapter';
|
||||||
@ -37,6 +35,7 @@ export * from '../test/generated-wrappers/i_multiplex_feature';
|
|||||||
export * from '../test/generated-wrappers/i_native_orders_events';
|
export * from '../test/generated-wrappers/i_native_orders_events';
|
||||||
export * from '../test/generated-wrappers/i_native_orders_feature';
|
export * from '../test/generated-wrappers/i_native_orders_feature';
|
||||||
export * from '../test/generated-wrappers/i_ownable_feature';
|
export * from '../test/generated-wrappers/i_ownable_feature';
|
||||||
|
export * from '../test/generated-wrappers/i_pancake_swap_feature';
|
||||||
export * from '../test/generated-wrappers/i_simple_function_registry_feature';
|
export * from '../test/generated-wrappers/i_simple_function_registry_feature';
|
||||||
export * from '../test/generated-wrappers/i_staking';
|
export * from '../test/generated-wrappers/i_staking';
|
||||||
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
|
export * from '../test/generated-wrappers/i_test_simple_function_registry_feature';
|
||||||
@ -66,9 +65,7 @@ export * from '../test/generated-wrappers/lib_signature';
|
|||||||
export * from '../test/generated-wrappers/lib_signature_rich_errors';
|
export * from '../test/generated-wrappers/lib_signature_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
|
export * from '../test/generated-wrappers/lib_simple_function_registry_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_simple_function_registry_storage';
|
export * from '../test/generated-wrappers/lib_simple_function_registry_storage';
|
||||||
export * from '../test/generated-wrappers/lib_spender_rich_errors';
|
|
||||||
export * from '../test/generated-wrappers/lib_storage';
|
export * from '../test/generated-wrappers/lib_storage';
|
||||||
export * from '../test/generated-wrappers/lib_token_spender_storage';
|
|
||||||
export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors';
|
export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors';
|
||||||
export * from '../test/generated-wrappers/lib_transform_erc20_storage';
|
export * from '../test/generated-wrappers/lib_transform_erc20_storage';
|
||||||
export * from '../test/generated-wrappers/lib_wallet_rich_errors';
|
export * from '../test/generated-wrappers/lib_wallet_rich_errors';
|
||||||
@ -86,9 +83,9 @@ export * from '../test/generated-wrappers/mixin_dodo_v2';
|
|||||||
export * from '../test/generated-wrappers/mixin_kyber';
|
export * from '../test/generated-wrappers/mixin_kyber';
|
||||||
export * from '../test/generated-wrappers/mixin_m_stable';
|
export * from '../test/generated-wrappers/mixin_m_stable';
|
||||||
export * from '../test/generated-wrappers/mixin_mooniswap';
|
export * from '../test/generated-wrappers/mixin_mooniswap';
|
||||||
|
export * from '../test/generated-wrappers/mixin_nerve';
|
||||||
export * from '../test/generated-wrappers/mixin_oasis';
|
export * from '../test/generated-wrappers/mixin_oasis';
|
||||||
export * from '../test/generated-wrappers/mixin_shell';
|
export * from '../test/generated-wrappers/mixin_shell';
|
||||||
export * from '../test/generated-wrappers/mixin_sushiswap';
|
|
||||||
export * from '../test/generated-wrappers/mixin_uniswap';
|
export * from '../test/generated-wrappers/mixin_uniswap';
|
||||||
export * from '../test/generated-wrappers/mixin_uniswap_v2';
|
export * from '../test/generated-wrappers/mixin_uniswap_v2';
|
||||||
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
|
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';
|
||||||
@ -100,6 +97,7 @@ export * from '../test/generated-wrappers/native_orders_info';
|
|||||||
export * from '../test/generated-wrappers/native_orders_protocol_fees';
|
export * from '../test/generated-wrappers/native_orders_protocol_fees';
|
||||||
export * from '../test/generated-wrappers/native_orders_settlement';
|
export * from '../test/generated-wrappers/native_orders_settlement';
|
||||||
export * from '../test/generated-wrappers/ownable_feature';
|
export * from '../test/generated-wrappers/ownable_feature';
|
||||||
|
export * from '../test/generated-wrappers/pancake_swap_feature';
|
||||||
export * from '../test/generated-wrappers/pay_taker_transformer';
|
export * from '../test/generated-wrappers/pay_taker_transformer';
|
||||||
export * from '../test/generated-wrappers/permissionless_transformer_deployer';
|
export * from '../test/generated-wrappers/permissionless_transformer_deployer';
|
||||||
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
|
export * from '../test/generated-wrappers/positive_slippage_fee_transformer';
|
||||||
@ -132,7 +130,6 @@ export * from '../test/generated-wrappers/test_rfq_origin_registration';
|
|||||||
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1';
|
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl1';
|
||||||
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2';
|
export * from '../test/generated-wrappers/test_simple_function_registry_feature_impl2';
|
||||||
export * from '../test/generated-wrappers/test_staking';
|
export * from '../test/generated-wrappers/test_staking';
|
||||||
export * from '../test/generated-wrappers/test_token_spender';
|
|
||||||
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
|
export * from '../test/generated-wrappers/test_token_spender_erc20_token';
|
||||||
export * from '../test/generated-wrappers/test_transform_erc20';
|
export * from '../test/generated-wrappers/test_transform_erc20';
|
||||||
export * from '../test/generated-wrappers/test_transformer_base';
|
export * from '../test/generated-wrappers/test_transformer_base';
|
||||||
@ -141,7 +138,6 @@ export * from '../test/generated-wrappers/test_transformer_host';
|
|||||||
export * from '../test/generated-wrappers/test_weth';
|
export * from '../test/generated-wrappers/test_weth';
|
||||||
export * from '../test/generated-wrappers/test_weth_transformer_host';
|
export * from '../test/generated-wrappers/test_weth_transformer_host';
|
||||||
export * from '../test/generated-wrappers/test_zero_ex_feature';
|
export * from '../test/generated-wrappers/test_zero_ex_feature';
|
||||||
export * from '../test/generated-wrappers/token_spender_feature';
|
|
||||||
export * from '../test/generated-wrappers/transform_erc20_feature';
|
export * from '../test/generated-wrappers/transform_erc20_feature';
|
||||||
export * from '../test/generated-wrappers/transformer';
|
export * from '../test/generated-wrappers/transformer';
|
||||||
export * from '../test/generated-wrappers/transformer_deployer';
|
export * from '../test/generated-wrappers/transformer_deployer';
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
"generated-artifacts/INativeOrdersFeature.json",
|
"generated-artifacts/INativeOrdersFeature.json",
|
||||||
"generated-artifacts/IOwnableFeature.json",
|
"generated-artifacts/IOwnableFeature.json",
|
||||||
"generated-artifacts/ISimpleFunctionRegistryFeature.json",
|
"generated-artifacts/ISimpleFunctionRegistryFeature.json",
|
||||||
"generated-artifacts/ITokenSpenderFeature.json",
|
|
||||||
"generated-artifacts/ITransformERC20Feature.json",
|
"generated-artifacts/ITransformERC20Feature.json",
|
||||||
"generated-artifacts/IZeroEx.json",
|
"generated-artifacts/IZeroEx.json",
|
||||||
"generated-artifacts/InitialMigration.json",
|
"generated-artifacts/InitialMigration.json",
|
||||||
@ -33,16 +32,14 @@
|
|||||||
"generated-artifacts/PayTakerTransformer.json",
|
"generated-artifacts/PayTakerTransformer.json",
|
||||||
"generated-artifacts/PositiveSlippageFeeTransformer.json",
|
"generated-artifacts/PositiveSlippageFeeTransformer.json",
|
||||||
"generated-artifacts/SimpleFunctionRegistryFeature.json",
|
"generated-artifacts/SimpleFunctionRegistryFeature.json",
|
||||||
"generated-artifacts/TokenSpenderFeature.json",
|
|
||||||
"generated-artifacts/TransformERC20Feature.json",
|
"generated-artifacts/TransformERC20Feature.json",
|
||||||
"generated-artifacts/WethTransformer.json",
|
"generated-artifacts/WethTransformer.json",
|
||||||
"generated-artifacts/ZeroEx.json",
|
"generated-artifacts/ZeroEx.json",
|
||||||
"test/generated-artifacts/AffiliateFeeTransformer.json",
|
"test/generated-artifacts/AffiliateFeeTransformer.json",
|
||||||
"test/generated-artifacts/AllowanceTarget.json",
|
|
||||||
"test/generated-artifacts/BatchFillNativeOrdersFeature.json",
|
"test/generated-artifacts/BatchFillNativeOrdersFeature.json",
|
||||||
"test/generated-artifacts/BootstrapFeature.json",
|
"test/generated-artifacts/BootstrapFeature.json",
|
||||||
"test/generated-artifacts/BridgeAdapter.json",
|
"test/generated-artifacts/BridgeAdapter.json",
|
||||||
"test/generated-artifacts/BridgeSource.json",
|
"test/generated-artifacts/BridgeProtocols.json",
|
||||||
"test/generated-artifacts/CurveLiquidityProvider.json",
|
"test/generated-artifacts/CurveLiquidityProvider.json",
|
||||||
"test/generated-artifacts/FeeCollector.json",
|
"test/generated-artifacts/FeeCollector.json",
|
||||||
"test/generated-artifacts/FeeCollectorController.json",
|
"test/generated-artifacts/FeeCollectorController.json",
|
||||||
@ -54,7 +51,6 @@
|
|||||||
"test/generated-artifacts/FixinTokenSpender.json",
|
"test/generated-artifacts/FixinTokenSpender.json",
|
||||||
"test/generated-artifacts/FlashWallet.json",
|
"test/generated-artifacts/FlashWallet.json",
|
||||||
"test/generated-artifacts/FullMigration.json",
|
"test/generated-artifacts/FullMigration.json",
|
||||||
"test/generated-artifacts/IAllowanceTarget.json",
|
|
||||||
"test/generated-artifacts/IBatchFillNativeOrdersFeature.json",
|
"test/generated-artifacts/IBatchFillNativeOrdersFeature.json",
|
||||||
"test/generated-artifacts/IBootstrapFeature.json",
|
"test/generated-artifacts/IBootstrapFeature.json",
|
||||||
"test/generated-artifacts/IBridgeAdapter.json",
|
"test/generated-artifacts/IBridgeAdapter.json",
|
||||||
@ -71,6 +67,7 @@
|
|||||||
"test/generated-artifacts/INativeOrdersEvents.json",
|
"test/generated-artifacts/INativeOrdersEvents.json",
|
||||||
"test/generated-artifacts/INativeOrdersFeature.json",
|
"test/generated-artifacts/INativeOrdersFeature.json",
|
||||||
"test/generated-artifacts/IOwnableFeature.json",
|
"test/generated-artifacts/IOwnableFeature.json",
|
||||||
|
"test/generated-artifacts/IPancakeSwapFeature.json",
|
||||||
"test/generated-artifacts/ISimpleFunctionRegistryFeature.json",
|
"test/generated-artifacts/ISimpleFunctionRegistryFeature.json",
|
||||||
"test/generated-artifacts/IStaking.json",
|
"test/generated-artifacts/IStaking.json",
|
||||||
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
|
"test/generated-artifacts/ITestSimpleFunctionRegistryFeature.json",
|
||||||
@ -100,9 +97,7 @@
|
|||||||
"test/generated-artifacts/LibSignatureRichErrors.json",
|
"test/generated-artifacts/LibSignatureRichErrors.json",
|
||||||
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
|
"test/generated-artifacts/LibSimpleFunctionRegistryRichErrors.json",
|
||||||
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
|
"test/generated-artifacts/LibSimpleFunctionRegistryStorage.json",
|
||||||
"test/generated-artifacts/LibSpenderRichErrors.json",
|
|
||||||
"test/generated-artifacts/LibStorage.json",
|
"test/generated-artifacts/LibStorage.json",
|
||||||
"test/generated-artifacts/LibTokenSpenderStorage.json",
|
|
||||||
"test/generated-artifacts/LibTransformERC20RichErrors.json",
|
"test/generated-artifacts/LibTransformERC20RichErrors.json",
|
||||||
"test/generated-artifacts/LibTransformERC20Storage.json",
|
"test/generated-artifacts/LibTransformERC20Storage.json",
|
||||||
"test/generated-artifacts/LibWalletRichErrors.json",
|
"test/generated-artifacts/LibWalletRichErrors.json",
|
||||||
@ -120,9 +115,9 @@
|
|||||||
"test/generated-artifacts/MixinKyber.json",
|
"test/generated-artifacts/MixinKyber.json",
|
||||||
"test/generated-artifacts/MixinMStable.json",
|
"test/generated-artifacts/MixinMStable.json",
|
||||||
"test/generated-artifacts/MixinMooniswap.json",
|
"test/generated-artifacts/MixinMooniswap.json",
|
||||||
|
"test/generated-artifacts/MixinNerve.json",
|
||||||
"test/generated-artifacts/MixinOasis.json",
|
"test/generated-artifacts/MixinOasis.json",
|
||||||
"test/generated-artifacts/MixinShell.json",
|
"test/generated-artifacts/MixinShell.json",
|
||||||
"test/generated-artifacts/MixinSushiswap.json",
|
|
||||||
"test/generated-artifacts/MixinUniswap.json",
|
"test/generated-artifacts/MixinUniswap.json",
|
||||||
"test/generated-artifacts/MixinUniswapV2.json",
|
"test/generated-artifacts/MixinUniswapV2.json",
|
||||||
"test/generated-artifacts/MixinZeroExBridge.json",
|
"test/generated-artifacts/MixinZeroExBridge.json",
|
||||||
@ -134,6 +129,7 @@
|
|||||||
"test/generated-artifacts/NativeOrdersProtocolFees.json",
|
"test/generated-artifacts/NativeOrdersProtocolFees.json",
|
||||||
"test/generated-artifacts/NativeOrdersSettlement.json",
|
"test/generated-artifacts/NativeOrdersSettlement.json",
|
||||||
"test/generated-artifacts/OwnableFeature.json",
|
"test/generated-artifacts/OwnableFeature.json",
|
||||||
|
"test/generated-artifacts/PancakeSwapFeature.json",
|
||||||
"test/generated-artifacts/PayTakerTransformer.json",
|
"test/generated-artifacts/PayTakerTransformer.json",
|
||||||
"test/generated-artifacts/PermissionlessTransformerDeployer.json",
|
"test/generated-artifacts/PermissionlessTransformerDeployer.json",
|
||||||
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
|
"test/generated-artifacts/PositiveSlippageFeeTransformer.json",
|
||||||
@ -166,7 +162,6 @@
|
|||||||
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json",
|
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl1.json",
|
||||||
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",
|
"test/generated-artifacts/TestSimpleFunctionRegistryFeatureImpl2.json",
|
||||||
"test/generated-artifacts/TestStaking.json",
|
"test/generated-artifacts/TestStaking.json",
|
||||||
"test/generated-artifacts/TestTokenSpender.json",
|
|
||||||
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
|
"test/generated-artifacts/TestTokenSpenderERC20Token.json",
|
||||||
"test/generated-artifacts/TestTransformERC20.json",
|
"test/generated-artifacts/TestTransformERC20.json",
|
||||||
"test/generated-artifacts/TestTransformerBase.json",
|
"test/generated-artifacts/TestTransformerBase.json",
|
||||||
@ -175,7 +170,6 @@
|
|||||||
"test/generated-artifacts/TestWeth.json",
|
"test/generated-artifacts/TestWeth.json",
|
||||||
"test/generated-artifacts/TestWethTransformerHost.json",
|
"test/generated-artifacts/TestWethTransformerHost.json",
|
||||||
"test/generated-artifacts/TestZeroExFeature.json",
|
"test/generated-artifacts/TestZeroExFeature.json",
|
||||||
"test/generated-artifacts/TokenSpenderFeature.json",
|
|
||||||
"test/generated-artifacts/TransformERC20Feature.json",
|
"test/generated-artifacts/TransformERC20Feature.json",
|
||||||
"test/generated-artifacts/Transformer.json",
|
"test/generated-artifacts/Transformer.json",
|
||||||
"test/generated-artifacts/TransformerDeployer.json",
|
"test/generated-artifacts/TransformerDeployer.json",
|
||||||
|
@ -17,6 +17,22 @@
|
|||||||
{
|
{
|
||||||
"note": "improve logging for alt RFQ requests",
|
"note": "improve logging for alt RFQ requests",
|
||||||
"pr": 158
|
"pr": 158
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Use new bridge source ID encoding.",
|
||||||
|
"pr": 162
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Refactor to provide chain id specific addresses",
|
||||||
|
"pr": 163
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added PancakeSwap and BakerySwap on Chain 56",
|
||||||
|
"pr": 163
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Added Nerve and Dodo (v1) to BSC",
|
||||||
|
"pr": 181
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -93,6 +93,10 @@ contract BalancerSampler {
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -151,6 +155,10 @@ contract BalancerSampler {
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
takerTokenAmounts[i] = amount;
|
takerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (takerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
|
@ -20,21 +20,23 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IBancor.sol";
|
import "./interfaces/IBancor.sol";
|
||||||
|
|
||||||
|
contract DeploymentConstants {}
|
||||||
|
|
||||||
|
contract BancorSampler is DeploymentConstants
|
||||||
contract BancorSampler is
|
|
||||||
DeploymentConstants
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/// @dev Base gas limit for Bancor calls.
|
/// @dev Base gas limit for Bancor calls.
|
||||||
uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k
|
uint256 constant private BANCOR_CALL_GAS = 300e3; // 300k
|
||||||
address constant private BANCOR_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
||||||
|
struct BancorSamplerOpts {
|
||||||
|
address registry;
|
||||||
|
address[][] paths;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Sample sell quotes from Bancor.
|
/// @dev Sample sell quotes from Bancor.
|
||||||
/// @param paths The paths to check for Bancor. Only the best is used
|
/// @param opts BancorSamplerOpts The Bancor registry contract address and paths
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
@ -43,7 +45,7 @@ contract BancorSampler is
|
|||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromBancor(
|
function sampleSellsFromBancor(
|
||||||
address[][] memory paths,
|
BancorSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -52,38 +54,13 @@ contract BancorSampler is
|
|||||||
view
|
view
|
||||||
returns (address bancorNetwork, address[] memory path, uint256[] memory makerTokenAmounts)
|
returns (address bancorNetwork, address[] memory path, uint256[] memory makerTokenAmounts)
|
||||||
{
|
{
|
||||||
bancorNetwork = _getBancorNetwork();
|
if (opts.paths.length == 0) {
|
||||||
if (paths.length == 0) {
|
|
||||||
return (bancorNetwork, path, makerTokenAmounts);
|
return (bancorNetwork, path, makerTokenAmounts);
|
||||||
}
|
}
|
||||||
uint256 maxBoughtAmount = 0;
|
(bancorNetwork, path) = _findBestPath(opts, takerToken, makerToken, takerTokenAmounts);
|
||||||
// Find the best path by selling the largest taker amount
|
makerTokenAmounts = new uint256[](takerTokenAmounts.length);
|
||||||
for (uint256 i = 0; i < paths.length; i++) {
|
|
||||||
if (paths[i].length < 2) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
for (uint256 i = 0; i < makerTokenAmounts.length; i++) {
|
||||||
IBancorNetwork(bancorNetwork)
|
|
||||||
.rateByPath
|
|
||||||
{gas: BANCOR_CALL_GAS}
|
|
||||||
(paths[i], takerTokenAmounts[takerTokenAmounts.length-1])
|
|
||||||
returns (uint256 amount)
|
|
||||||
{
|
|
||||||
if (amount > maxBoughtAmount) {
|
|
||||||
maxBoughtAmount = amount;
|
|
||||||
path = paths[i];
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Swallow failures, leaving all results as zero.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 numSamples = takerTokenAmounts.length;
|
|
||||||
makerTokenAmounts = new uint256[](numSamples);
|
|
||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
|
||||||
try
|
try
|
||||||
IBancorNetwork(bancorNetwork)
|
IBancorNetwork(bancorNetwork)
|
||||||
.rateByPath
|
.rateByPath
|
||||||
@ -92,6 +69,10 @@ contract BancorSampler is
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -101,7 +82,7 @@ contract BancorSampler is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from Bancor. Unimplemented
|
/// @dev Sample buy quotes from Bancor. Unimplemented
|
||||||
/// @param paths The paths to check for Bancor. Only the best is used
|
/// @param opts BancorSamplerOpts The Bancor registry contract address and paths
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
||||||
@ -110,7 +91,7 @@ contract BancorSampler is
|
|||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromBancor(
|
function sampleBuysFromBancor(
|
||||||
address[][] memory paths,
|
BancorSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -121,12 +102,51 @@ contract BancorSampler is
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getBancorNetwork()
|
function _findBestPath(
|
||||||
|
BancorSamplerOpts memory opts,
|
||||||
|
address takerToken,
|
||||||
|
address makerToken,
|
||||||
|
uint256[] memory takerTokenAmounts
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (address bancorNetwork, address[] memory path)
|
||||||
|
{
|
||||||
|
bancorNetwork = _getBancorNetwork(opts.registry);
|
||||||
|
if (opts.paths.length == 0) {
|
||||||
|
return (bancorNetwork, path);
|
||||||
|
}
|
||||||
|
uint256 maxBoughtAmount = 0;
|
||||||
|
// Find the best path by selling the largest taker amount
|
||||||
|
for (uint256 i = 0; i < opts.paths.length; i++) {
|
||||||
|
if (opts.paths[i].length < 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
IBancorNetwork(bancorNetwork)
|
||||||
|
.rateByPath
|
||||||
|
{gas: BANCOR_CALL_GAS}
|
||||||
|
(opts.paths[i], takerTokenAmounts[takerTokenAmounts.length-1])
|
||||||
|
returns (uint256 amount)
|
||||||
|
{
|
||||||
|
if (amount > maxBoughtAmount) {
|
||||||
|
maxBoughtAmount = amount;
|
||||||
|
path = opts.paths[i];
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Swallow failures, leaving all results as zero.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getBancorNetwork(address registry)
|
||||||
private
|
private
|
||||||
view
|
view
|
||||||
returns (address)
|
returns (address)
|
||||||
{
|
{
|
||||||
IBancorRegistry registry = IBancorRegistry(_getBancorRegistryAddress());
|
IBancorRegistry registry = IBancorRegistry(registry);
|
||||||
return registry.getAddress(registry.BANCOR_NETWORK());
|
return registry.getAddress(registry.BANCOR_NETWORK());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,11 +72,11 @@ contract CurveSampler is
|
|||||||
if (didSucceed) {
|
if (didSucceed) {
|
||||||
buyAmount = abi.decode(resultData, (uint256));
|
buyAmount = abi.decode(resultData, (uint256));
|
||||||
}
|
}
|
||||||
// Exit early if the amount is too high for the source to serve
|
makerTokenAmounts[i] = buyAmount;
|
||||||
if (buyAmount == 0) {
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
makerTokenAmounts[i] = buyAmount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +123,11 @@ contract CurveSampler is
|
|||||||
if (didSucceed) {
|
if (didSucceed) {
|
||||||
sellAmount = abi.decode(resultData, (uint256));
|
sellAmount = abi.decode(resultData, (uint256));
|
||||||
}
|
}
|
||||||
// Exit early if the amount is too high for the source to serve
|
takerTokenAmounts[i] = sellAmount;
|
||||||
if (sellAmount == 0) {
|
// Break early if there are 0 amounts
|
||||||
|
if (takerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
takerTokenAmounts[i] = sellAmount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./ApproximateBuys.sol";
|
import "./ApproximateBuys.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
@ -39,15 +38,19 @@ interface IDODO {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contract DODOSampler is
|
contract DODOSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils,
|
SamplerUtils,
|
||||||
ApproximateBuys
|
ApproximateBuys
|
||||||
{
|
{
|
||||||
|
|
||||||
/// @dev Gas limit for DODO calls.
|
/// @dev Gas limit for DODO calls.
|
||||||
uint256 constant private DODO_CALL_GAS = 300e3; // 300k
|
uint256 constant private DODO_CALL_GAS = 300e3; // 300k
|
||||||
|
struct DODOSamplerOpts {
|
||||||
|
address registry;
|
||||||
|
address helper;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Sample sell quotes from DODO.
|
/// @dev Sample sell quotes from DODO.
|
||||||
|
/// @param opts DODOSamplerOpts DODO Registry and helper addresses
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
@ -56,6 +59,7 @@ contract DODOSampler is
|
|||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromDODO(
|
function sampleSellsFromDODO(
|
||||||
|
DODOSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -68,14 +72,14 @@ contract DODOSampler is
|
|||||||
uint256 numSamples = takerTokenAmounts.length;
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
|
|
||||||
pool = IDODOZoo(_getDODORegistryAddress()).getDODO(takerToken, makerToken);
|
pool = IDODOZoo(opts.registry).getDODO(takerToken, makerToken);
|
||||||
address baseToken;
|
address baseToken;
|
||||||
// If pool exists we have the correct order of Base/Quote
|
// If pool exists we have the correct order of Base/Quote
|
||||||
if (pool != address(0)) {
|
if (pool != address(0)) {
|
||||||
baseToken = takerToken;
|
baseToken = takerToken;
|
||||||
sellBase = true;
|
sellBase = true;
|
||||||
} else {
|
} else {
|
||||||
pool = IDODOZoo(_getDODORegistryAddress()).getDODO(makerToken, takerToken);
|
pool = IDODOZoo(opts.registry).getDODO(makerToken, takerToken);
|
||||||
// No pool either direction
|
// No pool either direction
|
||||||
if (address(pool) == address(0)) {
|
if (address(pool) == address(0)) {
|
||||||
return (sellBase, pool, makerTokenAmounts);
|
return (sellBase, pool, makerTokenAmounts);
|
||||||
@ -91,19 +95,20 @@ contract DODOSampler is
|
|||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
uint256 buyAmount = _sampleSellForApproximateBuyFromDODO(
|
uint256 buyAmount = _sampleSellForApproximateBuyFromDODO(
|
||||||
abi.encode(takerToken, pool, baseToken), // taker token data
|
abi.encode(takerToken, pool, baseToken, opts.helper), // taker token data
|
||||||
abi.encode(makerToken, pool, baseToken), // maker token data
|
abi.encode(makerToken, pool, baseToken, opts.helper), // maker token data
|
||||||
takerTokenAmounts[i]
|
takerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
// Exit early if the amount is too high for the source to serve
|
makerTokenAmounts[i] = buyAmount;
|
||||||
if (buyAmount == 0) {
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
makerTokenAmounts[i] = buyAmount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from DODO.
|
/// @dev Sample buy quotes from DODO.
|
||||||
|
/// @param opts DODOSamplerOpts DODO Registry and helper addresses
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token sell amount for each sample.
|
/// @param makerTokenAmounts Maker token sell amount for each sample.
|
||||||
@ -112,6 +117,7 @@ contract DODOSampler is
|
|||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromDODO(
|
function sampleBuysFromDODO(
|
||||||
|
DODOSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -126,7 +132,7 @@ contract DODOSampler is
|
|||||||
|
|
||||||
// Pool is BASE/QUOTE
|
// Pool is BASE/QUOTE
|
||||||
// Look up the pool from the taker/maker combination
|
// Look up the pool from the taker/maker combination
|
||||||
pool = IDODOZoo(_getDODORegistryAddress()).getDODO(takerToken, makerToken);
|
pool = IDODOZoo(opts.registry).getDODO(takerToken, makerToken);
|
||||||
address baseToken;
|
address baseToken;
|
||||||
// If pool exists we have the correct order of Base/Quote
|
// If pool exists we have the correct order of Base/Quote
|
||||||
if (pool != address(0)) {
|
if (pool != address(0)) {
|
||||||
@ -134,7 +140,7 @@ contract DODOSampler is
|
|||||||
sellBase = true;
|
sellBase = true;
|
||||||
} else {
|
} else {
|
||||||
// Look up the pool from the maker/taker combination
|
// Look up the pool from the maker/taker combination
|
||||||
pool = IDODOZoo(_getDODORegistryAddress()).getDODO(makerToken, takerToken);
|
pool = IDODOZoo(opts.registry).getDODO(makerToken, takerToken);
|
||||||
// No pool either direction
|
// No pool either direction
|
||||||
if (address(pool) == address(0)) {
|
if (address(pool) == address(0)) {
|
||||||
return (sellBase, pool, takerTokenAmounts);
|
return (sellBase, pool, takerTokenAmounts);
|
||||||
@ -150,8 +156,8 @@ contract DODOSampler is
|
|||||||
|
|
||||||
takerTokenAmounts = _sampleApproximateBuys(
|
takerTokenAmounts = _sampleApproximateBuys(
|
||||||
ApproximateBuyQuoteOpts({
|
ApproximateBuyQuoteOpts({
|
||||||
makerTokenData: abi.encode(makerToken, pool, baseToken),
|
makerTokenData: abi.encode(makerToken, pool, baseToken, opts.helper),
|
||||||
takerTokenData: abi.encode(takerToken, pool, baseToken),
|
takerTokenData: abi.encode(takerToken, pool, baseToken, opts.helper),
|
||||||
getSellQuoteCallback: _sampleSellForApproximateBuyFromDODO
|
getSellQuoteCallback: _sampleSellForApproximateBuyFromDODO
|
||||||
}),
|
}),
|
||||||
makerTokenAmounts
|
makerTokenAmounts
|
||||||
@ -167,9 +173,9 @@ contract DODOSampler is
|
|||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
(address takerToken, address pool, address baseToken) = abi.decode(
|
(address takerToken, address pool, address baseToken, address helper) = abi.decode(
|
||||||
takerTokenData,
|
takerTokenData,
|
||||||
(address, address, address)
|
(address, address, address, address)
|
||||||
);
|
);
|
||||||
|
|
||||||
// We will get called to sell both the taker token and also to sell the maker token
|
// We will get called to sell both the taker token and also to sell the maker token
|
||||||
@ -189,7 +195,7 @@ contract DODOSampler is
|
|||||||
} else {
|
} else {
|
||||||
// If quote token then use helper, this is less accurate
|
// If quote token then use helper, this is less accurate
|
||||||
try
|
try
|
||||||
IDODOHelper(_getDODOHelperAddress()).querySellQuoteToken
|
IDODOHelper(helper).querySellQuoteToken
|
||||||
{gas: DODO_CALL_GAS}
|
{gas: DODO_CALL_GAS}
|
||||||
(pool, sellAmount)
|
(pool, sellAmount)
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./ApproximateBuys.sol";
|
import "./ApproximateBuys.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
@ -44,7 +43,6 @@ interface IDODOV2Pool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
contract DODOV2Sampler is
|
contract DODOV2Sampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils,
|
SamplerUtils,
|
||||||
ApproximateBuys
|
ApproximateBuys
|
||||||
{
|
{
|
||||||
@ -89,11 +87,11 @@ contract DODOV2Sampler is
|
|||||||
abi.encode(makerToken, pool, sellBase), // maker token data
|
abi.encode(makerToken, pool, sellBase), // maker token data
|
||||||
takerTokenAmounts[i]
|
takerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
// Exit early if the amount is too high for the source to serve
|
makerTokenAmounts[i] = buyAmount;
|
||||||
if (buyAmount == 0) {
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
makerTokenAmounts[i] = buyAmount;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,353 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6;
|
|
||||||
|
|
||||||
|
|
||||||
contract DeploymentConstants {
|
|
||||||
|
|
||||||
// solhint-disable separate-by-one-line-in-contract
|
|
||||||
|
|
||||||
// Mainnet addresses ///////////////////////////////////////////////////////
|
|
||||||
/// @dev Mainnet address of the WETH contract.
|
|
||||||
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
|
||||||
/// @dev Mainnet address of the KyberNetworkProxy contract.
|
|
||||||
address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
|
|
||||||
/// @dev Mainnet address of the KyberHintHandler contract.
|
|
||||||
address constant private KYBER_HINT_HANDLER_ADDRESS = 0xa1C0Fa73c39CFBcC11ec9Eb1Afc665aba9996E2C;
|
|
||||||
/// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
|
||||||
address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
|
|
||||||
/// @dev Mainnet address of the `UniswapV2Router01` contract.
|
|
||||||
address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
|
||||||
/// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
|
||||||
address constant private ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D;
|
|
||||||
/// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
|
||||||
address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x8ED95d1746bf1E4dAb58d8ED4724f1Ef95B20Db0;
|
|
||||||
///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
|
||||||
address constant private DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
|
|
||||||
/// @dev Mainnet address of the `Chai` contract
|
|
||||||
address constant private CHAI_ADDRESS = 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215;
|
|
||||||
/// @dev Mainnet address of the 0x DevUtils contract.
|
|
||||||
address constant private DEV_UTILS_ADDRESS = 0x74134CF88b21383713E096a5ecF59e297dc7f547;
|
|
||||||
/// @dev Kyber ETH pseudo-address.
|
|
||||||
address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
||||||
/// @dev Mainnet address of the dYdX contract.
|
|
||||||
address constant private DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
|
|
||||||
/// @dev Mainnet address of the GST2 contract
|
|
||||||
address constant private GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
|
|
||||||
/// @dev Mainnet address of the GST Collector
|
|
||||||
address constant private GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
|
|
||||||
/// @dev Mainnet address of the mStable mUSD contract.
|
|
||||||
address constant private MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
|
|
||||||
/// @dev Mainnet address of the Mooniswap Registry contract
|
|
||||||
address constant private MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
|
|
||||||
/// @dev Mainnet address of the Shell contract
|
|
||||||
address constant private SHELL_CONTRACT = 0x2E703D658f8dd21709a7B458967aB4081F8D3d05;
|
|
||||||
/// @dev Mainnet address of the DODO Registry (ZOO) contract
|
|
||||||
address constant private DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
|
|
||||||
/// @dev Mainnet address of the DODO Helper contract
|
|
||||||
address constant private DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
|
|
||||||
/// @dev Mainnet address of the Bancor Registry contract
|
|
||||||
address constant private BANCOR_REGISTRY = 0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4;
|
|
||||||
|
|
||||||
// // Ropsten addresses ///////////////////////////////////////////////////////
|
|
||||||
// /// @dev Mainnet address of the WETH contract.
|
|
||||||
// address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
|
|
||||||
// /// @dev Mainnet address of the KyberNetworkProxy contract.
|
|
||||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0xd719c34261e099Fdb33030ac8909d5788D3039C4;
|
|
||||||
// /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
|
||||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0x9c83dCE8CA20E9aAF9D3efc003b2ea62aBC08351;
|
|
||||||
// /// @dev Mainnet address of the `UniswapV2Router01` contract.
|
|
||||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
|
||||||
// /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
|
||||||
// address constant private ETH2DAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
|
||||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xb344afeD348de15eb4a9e180205A2B0739628339;
|
|
||||||
// ///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
|
||||||
// address constant private DAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the `Chai` contract
|
|
||||||
// address constant private CHAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the 0x DevUtils contract.
|
|
||||||
// address constant private DEV_UTILS_ADDRESS = 0xC812AF3f3fBC62F76ea4262576EC0f49dB8B7f1c;
|
|
||||||
// /// @dev Kyber ETH pseudo-address.
|
|
||||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
||||||
// /// @dev Mainnet address of the dYdX contract.
|
|
||||||
// address constant private DYDX_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the GST2 contract
|
|
||||||
// address constant private GST_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the GST Collector
|
|
||||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
|
||||||
// address constant private MUSD_ADDRESS = 0x4E1000616990D83e56f4b5fC6CC8602DcfD20459;
|
|
||||||
|
|
||||||
// // Rinkeby addresses ///////////////////////////////////////////////////////
|
|
||||||
// /// @dev Mainnet address of the WETH contract.
|
|
||||||
// address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
|
|
||||||
// /// @dev Mainnet address of the KyberNetworkProxy contract.
|
|
||||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x0d5371e5EE23dec7DF251A8957279629aa79E9C5;
|
|
||||||
// /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
|
|
||||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36;
|
|
||||||
// /// @dev Mainnet address of the `UniswapV2Router01` contract.
|
|
||||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
|
||||||
// /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
|
|
||||||
// address constant private ETH2DAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the `ERC20BridgeProxy` contract
|
|
||||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xA2AA4bEFED748Fba27a3bE7Dfd2C4b2c6DB1F49B;
|
|
||||||
// ///@dev Mainnet address of the `Dai` (multi-collateral) contract
|
|
||||||
// address constant private DAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the `Chai` contract
|
|
||||||
// address constant private CHAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the 0x DevUtils contract.
|
|
||||||
// address constant private DEV_UTILS_ADDRESS = 0x46B5BC959e8A754c0256FFF73bF34A52Ad5CdfA9;
|
|
||||||
// /// @dev Kyber ETH pseudo-address.
|
|
||||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
||||||
// /// @dev Mainnet address of the dYdX contract.
|
|
||||||
// address constant private DYDX_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the GST2 contract
|
|
||||||
// address constant private GST_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the GST Collector
|
|
||||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
|
||||||
// address constant private MUSD_ADDRESS = address(0);
|
|
||||||
|
|
||||||
// // Kovan addresses /////////////////////////////////////////////////////////
|
|
||||||
// /// @dev Kovan address of the WETH contract.
|
|
||||||
// address constant private WETH_ADDRESS = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
|
|
||||||
// /// @dev Kovan address of the KyberNetworkProxy contract.
|
|
||||||
// address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D;
|
|
||||||
// /// @dev Kovan address of the `UniswapExchangeFactory` contract.
|
|
||||||
// address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30;
|
|
||||||
// /// @dev Kovan address of the `UniswapV2Router01` contract.
|
|
||||||
// address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
|
|
||||||
// /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
|
|
||||||
// address constant private ETH2DAI_ADDRESS = 0xe325acB9765b02b8b418199bf9650972299235F4;
|
|
||||||
// /// @dev Kovan address of the `ERC20BridgeProxy` contract
|
|
||||||
// address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x3577552C1Fb7A44aD76BeEB7aB53251668A21F8D;
|
|
||||||
// /// @dev Kovan address of the `Chai` contract
|
|
||||||
// address constant private CHAI_ADDRESS = address(0);
|
|
||||||
// /// @dev Kovan address of the `Dai` (multi-collateral) contract
|
|
||||||
// address constant private DAI_ADDRESS = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
|
|
||||||
// /// @dev Kovan address of the 0x DevUtils contract.
|
|
||||||
// address constant private DEV_UTILS_ADDRESS = 0x9402639A828BdF4E9e4103ac3B69E1a6E522eB59;
|
|
||||||
// /// @dev Kyber ETH pseudo-address.
|
|
||||||
// address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
|
||||||
// /// @dev Kovan address of the dYdX contract.
|
|
||||||
// address constant private DYDX_ADDRESS = address(0);
|
|
||||||
// /// @dev Kovan address of the GST2 contract
|
|
||||||
// address constant private GST_ADDRESS = address(0);
|
|
||||||
// /// @dev Kovan address of the GST Collector
|
|
||||||
// address constant private GST_COLLECTOR_ADDRESS = address(0);
|
|
||||||
// /// @dev Mainnet address of the mStable mUSD contract.
|
|
||||||
// address constant private MUSD_ADDRESS = address(0);
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the `KyberNetworkProxy` address.
|
|
||||||
/// @return kyberAddress The `IKyberNetworkProxy` address.
|
|
||||||
function _getKyberNetworkProxyAddress()
|
|
||||||
virtual
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address kyberAddress)
|
|
||||||
{
|
|
||||||
return KYBER_NETWORK_PROXY_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the `KyberHintHandler` address.
|
|
||||||
/// @return hintHandlerAddress The `IKyberHintHandler` address.
|
|
||||||
function _getKyberHintHandlerAddress()
|
|
||||||
virtual
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address hintHandlerAddress)
|
|
||||||
{
|
|
||||||
return KYBER_HINT_HANDLER_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the WETH address.
|
|
||||||
/// @return wethAddress The WETH address.
|
|
||||||
function _getWethAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address wethAddress)
|
|
||||||
{
|
|
||||||
return WETH_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the `UniswapExchangeFactory` address.
|
|
||||||
/// @return uniswapAddress The `UniswapExchangeFactory` address.
|
|
||||||
function _getUniswapExchangeFactoryAddress()
|
|
||||||
virtual
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address uniswapAddress)
|
|
||||||
{
|
|
||||||
return UNISWAP_EXCHANGE_FACTORY_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the `UniswapV2Router01` address.
|
|
||||||
/// @return uniswapRouterAddress The `UniswapV2Router01` address.
|
|
||||||
function _getUniswapV2Router01Address()
|
|
||||||
virtual
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address uniswapRouterAddress)
|
|
||||||
{
|
|
||||||
return UNISWAP_V2_ROUTER_01_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Eth2Dai `MatchingMarket` contract.
|
|
||||||
/// @return eth2daiAddress The Eth2Dai `MatchingMarket` contract.
|
|
||||||
function _getEth2DaiAddress()
|
|
||||||
virtual
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address eth2daiAddress)
|
|
||||||
{
|
|
||||||
return ETH2DAI_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the `ERC20BridgeProxy` contract.
|
|
||||||
/// @return erc20BridgeProxyAddress The `ERC20BridgeProxy` contract.
|
|
||||||
function _getERC20BridgeProxyAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address erc20BridgeProxyAddress)
|
|
||||||
{
|
|
||||||
return ERC20_BRIDGE_PROXY_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the `Dai` contract.
|
|
||||||
/// @return daiAddress The `Dai` contract.
|
|
||||||
function _getDaiAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address daiAddress)
|
|
||||||
{
|
|
||||||
return DAI_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the `Chai` contract.
|
|
||||||
/// @return chaiAddress The `Chai` contract.
|
|
||||||
function _getChaiAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address chaiAddress)
|
|
||||||
{
|
|
||||||
return CHAI_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the 0x `DevUtils` contract address.
|
|
||||||
/// @return devUtils The 0x `DevUtils` contract address.
|
|
||||||
function _getDevUtilsAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address devUtils)
|
|
||||||
{
|
|
||||||
return DEV_UTILS_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev Overridable way to get the DyDx contract.
|
|
||||||
/// @return dydxAddress exchange The DyDx exchange contract.
|
|
||||||
function _getDydxAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address dydxAddress)
|
|
||||||
{
|
|
||||||
return DYDX_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the GST2 contract address.
|
|
||||||
/// @return gst The GST contract.
|
|
||||||
function _getGstAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address gst)
|
|
||||||
{
|
|
||||||
return GST_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the GST Collector address.
|
|
||||||
/// @return collector The GST collector address.
|
|
||||||
function _getGstCollectorAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address collector)
|
|
||||||
{
|
|
||||||
return GST_COLLECTOR_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the mStable mUSD address.
|
|
||||||
/// @return musd The mStable mUSD address.
|
|
||||||
function _getMUsdAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address musd)
|
|
||||||
{
|
|
||||||
return MUSD_ADDRESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Mooniswap registry address.
|
|
||||||
/// @return registry The Mooniswap registry address.
|
|
||||||
function _getMooniswapAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address)
|
|
||||||
{
|
|
||||||
return MOONISWAP_REGISTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Shell contract address.
|
|
||||||
/// @return registry The Shell contract address.
|
|
||||||
function _getShellAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address registry)
|
|
||||||
{
|
|
||||||
return SHELL_CONTRACT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the DODO Registry contract address.
|
|
||||||
/// @return registry The DODO Registry contract address.
|
|
||||||
function _getDODORegistryAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address registry)
|
|
||||||
{
|
|
||||||
return DODO_REGISTRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the DODO Helper contract address.
|
|
||||||
/// @return registry The DODO Helper contract address.
|
|
||||||
function _getDODOHelperAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address registry)
|
|
||||||
{
|
|
||||||
return DODO_HELPER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @dev An overridable way to retrieve the Bancor Registry contract address.
|
|
||||||
/// @return registry The Bancor registry contract address.
|
|
||||||
function _getBancorRegistryAddress()
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address registry)
|
|
||||||
{
|
|
||||||
return BANCOR_REGISTRY;
|
|
||||||
}
|
|
||||||
}
|
|
@ -33,7 +33,6 @@ import "./MStableSampler.sol";
|
|||||||
import "./MooniswapSampler.sol";
|
import "./MooniswapSampler.sol";
|
||||||
import "./NativeOrderSampler.sol";
|
import "./NativeOrderSampler.sol";
|
||||||
import "./ShellSampler.sol";
|
import "./ShellSampler.sol";
|
||||||
import "./SushiSwapSampler.sol";
|
|
||||||
import "./TwoHopSampler.sol";
|
import "./TwoHopSampler.sol";
|
||||||
import "./UniswapSampler.sol";
|
import "./UniswapSampler.sol";
|
||||||
import "./UniswapV2Sampler.sol";
|
import "./UniswapV2Sampler.sol";
|
||||||
@ -54,7 +53,6 @@ contract ERC20BridgeSampler is
|
|||||||
MultiBridgeSampler,
|
MultiBridgeSampler,
|
||||||
NativeOrderSampler,
|
NativeOrderSampler,
|
||||||
ShellSampler,
|
ShellSampler,
|
||||||
SushiSwapSampler,
|
|
||||||
TwoHopSampler,
|
TwoHopSampler,
|
||||||
UniswapSampler,
|
UniswapSampler,
|
||||||
UniswapV2Sampler,
|
UniswapV2Sampler,
|
||||||
|
@ -20,25 +20,25 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IEth2Dai.sol";
|
import "./interfaces/IEth2Dai.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
|
|
||||||
contract Eth2DaiSampler is
|
contract Eth2DaiSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils
|
SamplerUtils
|
||||||
{
|
{
|
||||||
/// @dev Base gas limit for Eth2Dai calls.
|
/// @dev Base gas limit for Eth2Dai calls.
|
||||||
uint256 constant private ETH2DAI_CALL_GAS = 1000e3; // 1m
|
uint256 constant private ETH2DAI_CALL_GAS = 1000e3; // 1m
|
||||||
|
|
||||||
/// @dev Sample sell quotes from Eth2Dai/Oasis.
|
/// @dev Sample sell quotes from Eth2Dai/Oasis.
|
||||||
|
/// @param router Address of the Eth2Dai/Oasis contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromEth2Dai(
|
function sampleSellsFromEth2Dai(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -52,12 +52,16 @@ contract Eth2DaiSampler is
|
|||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
try
|
try
|
||||||
IEth2Dai(_getEth2DaiAddress()).getBuyAmount
|
IEth2Dai(router).getBuyAmount
|
||||||
{gas: ETH2DAI_CALL_GAS}
|
{gas: ETH2DAI_CALL_GAS}
|
||||||
(makerToken, takerToken, takerTokenAmounts[i])
|
(makerToken, takerToken, takerTokenAmounts[i])
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -66,12 +70,14 @@ contract Eth2DaiSampler is
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from Eth2Dai/Oasis.
|
/// @dev Sample buy quotes from Eth2Dai/Oasis.
|
||||||
|
/// @param router Address of the Eth2Dai/Oasis contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Maker token sell amount for each sample.
|
/// @param takerTokenAmounts Maker token sell amount for each sample.
|
||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromEth2Dai(
|
function sampleBuysFromEth2Dai(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -85,12 +91,16 @@ contract Eth2DaiSampler is
|
|||||||
takerTokenAmounts = new uint256[](numSamples);
|
takerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
try
|
try
|
||||||
IEth2Dai(_getEth2DaiAddress()).getPayAmount
|
IEth2Dai(router).getPayAmount
|
||||||
{gas: ETH2DAI_CALL_GAS}
|
{gas: ETH2DAI_CALL_GAS}
|
||||||
(takerToken, makerToken, makerTokenAmounts[i])
|
(takerToken, makerToken, makerTokenAmounts[i])
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
takerTokenAmounts[i] = amount;
|
takerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (takerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
|
@ -20,22 +20,30 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IKyberNetwork.sol";
|
import "./interfaces/IKyberNetwork.sol";
|
||||||
import "./ApproximateBuys.sol";
|
import "./ApproximateBuys.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
|
|
||||||
contract KyberSampler is
|
contract KyberSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils,
|
SamplerUtils,
|
||||||
ApproximateBuys
|
ApproximateBuys
|
||||||
{
|
{
|
||||||
/// @dev Gas limit for Kyber calls.
|
/// @dev Gas limit for Kyber calls.
|
||||||
uint256 constant private KYBER_CALL_GAS = 500e3; // 500k
|
uint256 constant private KYBER_CALL_GAS = 500e3; // 500k
|
||||||
|
/// @dev Kyber ETH pseudo-address.
|
||||||
|
address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||||
|
|
||||||
|
struct KyberSamplerOpts {
|
||||||
|
uint256 reserveOffset;
|
||||||
|
address hintHandler;
|
||||||
|
address networkProxy;
|
||||||
|
address weth;
|
||||||
|
bytes hint;
|
||||||
|
}
|
||||||
|
|
||||||
/// @dev Sample sell quotes from Kyber.
|
/// @dev Sample sell quotes from Kyber.
|
||||||
/// @param reserveOffset The nth reserve
|
/// @param opts KyberSamplerOpts The nth reserve
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
@ -43,7 +51,7 @@ contract KyberSampler is
|
|||||||
/// @return hint The hint for the selected reserve
|
/// @return hint The hint for the selected reserve
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token amount.
|
/// @return makerTokenAmounts Maker amounts bought at each taker token amount.
|
||||||
function sampleSellsFromKyberNetwork(
|
function sampleSellsFromKyberNetwork(
|
||||||
uint256 reserveOffset,
|
KyberSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -53,31 +61,32 @@ contract KyberSampler is
|
|||||||
returns (bytes32 reserveId, bytes memory hint, uint256[] memory makerTokenAmounts)
|
returns (bytes32 reserveId, bytes memory hint, uint256[] memory makerTokenAmounts)
|
||||||
{
|
{
|
||||||
_assertValidPair(makerToken, takerToken);
|
_assertValidPair(makerToken, takerToken);
|
||||||
reserveId = _getNextReserveId(takerToken, makerToken, reserveOffset);
|
reserveId = _getNextReserveId(opts, takerToken, makerToken);
|
||||||
if (reserveId == 0x0) {
|
if (reserveId == 0x0) {
|
||||||
return (reserveId, hint, makerTokenAmounts);
|
return (reserveId, hint, makerTokenAmounts);
|
||||||
}
|
}
|
||||||
hint = this.encodeKyberHint(reserveId, takerToken, makerToken);
|
opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken);
|
||||||
|
hint = opts.hint;
|
||||||
|
|
||||||
uint256 numSamples = takerTokenAmounts.length;
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
uint256 value = this.sampleSellFromKyberNetwork(
|
uint256 value = this.sampleSellFromKyberNetwork(
|
||||||
hint,
|
opts,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerTokenAmounts[i]
|
takerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
// Return early if the source has no liquidity
|
|
||||||
if (value == 0) {
|
|
||||||
return (reserveId, hint, makerTokenAmounts);
|
|
||||||
}
|
|
||||||
makerTokenAmounts[i] = value;
|
makerTokenAmounts[i] = value;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from Kyber.
|
/// @dev Sample buy quotes from Kyber.
|
||||||
/// @param reserveOffset The nth reserve
|
/// @param opts KyberSamplerOpts The nth reserve
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
||||||
@ -85,7 +94,7 @@ contract KyberSampler is
|
|||||||
/// @return hint The hint for the selected reserve
|
/// @return hint The hint for the selected reserve
|
||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token amount.
|
/// @return takerTokenAmounts Taker amounts sold at each maker token amount.
|
||||||
function sampleBuysFromKyberNetwork(
|
function sampleBuysFromKyberNetwork(
|
||||||
uint256 reserveOffset,
|
KyberSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -96,16 +105,17 @@ contract KyberSampler is
|
|||||||
{
|
{
|
||||||
_assertValidPair(makerToken, takerToken);
|
_assertValidPair(makerToken, takerToken);
|
||||||
|
|
||||||
reserveId = _getNextReserveId(takerToken, makerToken, reserveOffset);
|
reserveId = _getNextReserveId(opts, takerToken, makerToken);
|
||||||
if (reserveId == 0x0) {
|
if (reserveId == 0x0) {
|
||||||
return (reserveId, hint, takerTokenAmounts);
|
return (reserveId, hint, takerTokenAmounts);
|
||||||
}
|
}
|
||||||
hint = this.encodeKyberHint(reserveId, takerToken, makerToken);
|
opts.hint = this.encodeKyberHint(opts, reserveId, takerToken, makerToken);
|
||||||
|
hint = opts.hint;
|
||||||
|
|
||||||
takerTokenAmounts = _sampleApproximateBuys(
|
takerTokenAmounts = _sampleApproximateBuys(
|
||||||
ApproximateBuyQuoteOpts({
|
ApproximateBuyQuoteOpts({
|
||||||
makerTokenData: abi.encode(makerToken, hint),
|
makerTokenData: abi.encode(makerToken, opts),
|
||||||
takerTokenData: abi.encode(takerToken, hint),
|
takerTokenData: abi.encode(takerToken, opts),
|
||||||
getSellQuoteCallback: _sampleSellForApproximateBuyFromKyber
|
getSellQuoteCallback: _sampleSellForApproximateBuyFromKyber
|
||||||
}),
|
}),
|
||||||
makerTokenAmounts
|
makerTokenAmounts
|
||||||
@ -114,6 +124,7 @@ contract KyberSampler is
|
|||||||
}
|
}
|
||||||
|
|
||||||
function encodeKyberHint(
|
function encodeKyberHint(
|
||||||
|
KyberSamplerOpts memory opts,
|
||||||
bytes32 reserveId,
|
bytes32 reserveId,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken
|
address makerToken
|
||||||
@ -123,14 +134,14 @@ contract KyberSampler is
|
|||||||
returns (bytes memory hint)
|
returns (bytes memory hint)
|
||||||
{
|
{
|
||||||
// Build a hint selecting the single reserve
|
// Build a hint selecting the single reserve
|
||||||
IKyberHintHandler kyberHint = IKyberHintHandler(_getKyberHintHandlerAddress());
|
IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler);
|
||||||
|
|
||||||
// All other reserves should be ignored with this hint
|
// All other reserves should be ignored with this hint
|
||||||
bytes32[] memory selectedReserves = new bytes32[](1);
|
bytes32[] memory selectedReserves = new bytes32[](1);
|
||||||
selectedReserves[0] = reserveId;
|
selectedReserves[0] = reserveId;
|
||||||
uint256[] memory emptySplits = new uint256[](0);
|
uint256[] memory emptySplits = new uint256[](0);
|
||||||
|
|
||||||
if (takerToken == _getWethAddress()) {
|
if (takerToken == opts.weth) {
|
||||||
// ETH to Token
|
// ETH to Token
|
||||||
try
|
try
|
||||||
kyberHint.buildEthToTokenHint
|
kyberHint.buildEthToTokenHint
|
||||||
@ -147,7 +158,7 @@ contract KyberSampler is
|
|||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
}
|
}
|
||||||
} else if (makerToken == _getWethAddress()) {
|
} else if (makerToken == opts.weth) {
|
||||||
// Token to ETH
|
// Token to ETH
|
||||||
try
|
try
|
||||||
kyberHint.buildTokenToEthHint
|
kyberHint.buildTokenToEthHint
|
||||||
@ -199,13 +210,13 @@ contract KyberSampler is
|
|||||||
view
|
view
|
||||||
returns (uint256)
|
returns (uint256)
|
||||||
{
|
{
|
||||||
(address makerToken, bytes memory hint) =
|
(address makerToken, KyberSamplerOpts memory opts) =
|
||||||
abi.decode(makerTokenData, (address, bytes));
|
abi.decode(makerTokenData, (address, KyberSamplerOpts));
|
||||||
(address takerToken, ) =
|
(address takerToken, ) =
|
||||||
abi.decode(takerTokenData, (address, bytes));
|
abi.decode(takerTokenData, (address, KyberSamplerOpts));
|
||||||
try
|
try
|
||||||
this.sampleSellFromKyberNetwork
|
this.sampleSellFromKyberNetwork
|
||||||
(hint, takerToken, makerToken, sellAmount)
|
(opts, takerToken, makerToken, sellAmount)
|
||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
return amount;
|
return amount;
|
||||||
@ -216,7 +227,7 @@ contract KyberSampler is
|
|||||||
}
|
}
|
||||||
|
|
||||||
function sampleSellFromKyberNetwork(
|
function sampleSellFromKyberNetwork(
|
||||||
bytes memory hint,
|
KyberSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256 takerTokenAmount
|
uint256 takerTokenAmount
|
||||||
@ -226,19 +237,19 @@ contract KyberSampler is
|
|||||||
returns (uint256 makerTokenAmount)
|
returns (uint256 makerTokenAmount)
|
||||||
{
|
{
|
||||||
// If there is no hint do not continue
|
// If there is no hint do not continue
|
||||||
if (hint.length == 0) {
|
if (opts.hint.length == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
IKyberNetworkProxy(_getKyberNetworkProxyAddress()).getExpectedRateAfterFee
|
IKyberNetworkProxy(opts.networkProxy).getExpectedRateAfterFee
|
||||||
{gas: KYBER_CALL_GAS}
|
{gas: KYBER_CALL_GAS}
|
||||||
(
|
(
|
||||||
takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
|
takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken,
|
||||||
makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
|
makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken,
|
||||||
takerTokenAmount,
|
takerTokenAmount,
|
||||||
0, // fee
|
0, // fee
|
||||||
hint
|
opts.hint
|
||||||
)
|
)
|
||||||
returns (uint256 rate)
|
returns (uint256 rate)
|
||||||
{
|
{
|
||||||
@ -258,28 +269,28 @@ contract KyberSampler is
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _getNextReserveId(
|
function _getNextReserveId(
|
||||||
|
KyberSamplerOpts memory opts,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken
|
||||||
uint256 reserveOffset
|
|
||||||
)
|
)
|
||||||
internal
|
internal
|
||||||
view
|
view
|
||||||
returns (bytes32 reserveId)
|
returns (bytes32 reserveId)
|
||||||
{
|
{
|
||||||
// Fetch the registered reserves for this pair
|
// Fetch the registered reserves for this pair
|
||||||
IKyberHintHandler kyberHint = IKyberHintHandler(_getKyberHintHandlerAddress());
|
IKyberHintHandler kyberHint = IKyberHintHandler(opts.hintHandler);
|
||||||
(bytes32[] memory reserveIds, ,) = kyberHint.getTradingReserves(
|
(bytes32[] memory reserveIds, ,) = kyberHint.getTradingReserves(
|
||||||
takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
|
takerToken == opts.weth ? KYBER_ETH_ADDRESS : takerToken,
|
||||||
makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
|
makerToken == opts.weth ? KYBER_ETH_ADDRESS : makerToken,
|
||||||
true,
|
true,
|
||||||
new bytes(0) // empty hint
|
new bytes(0) // empty hint
|
||||||
);
|
);
|
||||||
|
|
||||||
if (reserveOffset >= reserveIds.length) {
|
if (opts.reserveOffset >= reserveIds.length) {
|
||||||
return 0x0;
|
return 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reserveId = reserveIds[reserveOffset];
|
reserveId = reserveIds[opts.reserveOffset];
|
||||||
// Ignore Kyber Bridged Reserves (0xbb)
|
// Ignore Kyber Bridged Reserves (0xbb)
|
||||||
if (uint256(reserveId >> 248) == 0xbb) {
|
if (uint256(reserveId >> 248) == 0xbb) {
|
||||||
return 0x0;
|
return 0x0;
|
||||||
|
@ -66,6 +66,10 @@ contract LiquidityProviderSampler is
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
|
@ -20,27 +20,27 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IMStable.sol";
|
import "./interfaces/IMStable.sol";
|
||||||
import "./ApproximateBuys.sol";
|
import "./ApproximateBuys.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
|
|
||||||
contract MStableSampler is
|
contract MStableSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils,
|
SamplerUtils,
|
||||||
ApproximateBuys
|
ApproximateBuys
|
||||||
{
|
{
|
||||||
/// @dev Default gas limit for mStable calls.
|
/// @dev Default gas limit for mStable calls.
|
||||||
uint256 constant private DEFAULT_CALL_GAS = 800e3; // 800k
|
uint256 constant private DEFAULT_CALL_GAS = 800e3; // 800k
|
||||||
|
|
||||||
/// @dev Sample sell quotes from the mStable mUSD contract
|
/// @dev Sample sell quotes from the mStable contract
|
||||||
|
/// @param router Address of the mStable contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromMStable(
|
function sampleSellsFromMStable(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -55,12 +55,16 @@ contract MStableSampler is
|
|||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
try
|
try
|
||||||
IMStable(_getMUsdAddress()).getSwapOutput
|
IMStable(router).getSwapOutput
|
||||||
{gas: DEFAULT_CALL_GAS}
|
{gas: DEFAULT_CALL_GAS}
|
||||||
(takerToken, makerToken, takerTokenAmounts[i])
|
(takerToken, makerToken, takerTokenAmounts[i])
|
||||||
returns (bool, string memory, uint256 amount)
|
returns (bool, string memory, uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -68,13 +72,15 @@ contract MStableSampler is
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Sample buy quotes from MStable mUSD contract
|
/// @dev Sample buy quotes from MStable contract
|
||||||
|
/// @param router Address of the mStable contract
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
/// @param makerTokenAmounts Maker token buy amount for each sample.
|
||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromMStable(
|
function sampleBuysFromMStable(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -85,8 +91,8 @@ contract MStableSampler is
|
|||||||
{
|
{
|
||||||
return _sampleApproximateBuys(
|
return _sampleApproximateBuys(
|
||||||
ApproximateBuyQuoteOpts({
|
ApproximateBuyQuoteOpts({
|
||||||
makerTokenData: abi.encode(makerToken),
|
makerTokenData: abi.encode(makerToken, router),
|
||||||
takerTokenData: abi.encode(takerToken),
|
takerTokenData: abi.encode(takerToken, router),
|
||||||
getSellQuoteCallback: _sampleSellForApproximateBuyFromMStable
|
getSellQuoteCallback: _sampleSellForApproximateBuyFromMStable
|
||||||
}),
|
}),
|
||||||
makerTokenAmounts
|
makerTokenAmounts
|
||||||
@ -102,13 +108,13 @@ contract MStableSampler is
|
|||||||
view
|
view
|
||||||
returns (uint256 buyAmount)
|
returns (uint256 buyAmount)
|
||||||
{
|
{
|
||||||
(address takerToken) =
|
(address takerToken, address router) =
|
||||||
abi.decode(takerTokenData, (address));
|
abi.decode(takerTokenData, (address, address));
|
||||||
(address makerToken) =
|
(address makerToken) =
|
||||||
abi.decode(makerTokenData, (address));
|
abi.decode(makerTokenData, (address));
|
||||||
try
|
try
|
||||||
this.sampleSellsFromMStable
|
this.sampleSellsFromMStable
|
||||||
(takerToken, makerToken, _toSingleValueArray(sellAmount))
|
(router, takerToken, makerToken, _toSingleValueArray(sellAmount))
|
||||||
returns (uint256[] memory amounts)
|
returns (uint256[] memory amounts)
|
||||||
{
|
{
|
||||||
return amounts[0];
|
return amounts[0];
|
||||||
|
@ -20,14 +20,12 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IMooniswap.sol";
|
import "./interfaces/IMooniswap.sol";
|
||||||
import "./ApproximateBuys.sol";
|
import "./ApproximateBuys.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
|
|
||||||
contract MooniswapSampler is
|
contract MooniswapSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils,
|
SamplerUtils,
|
||||||
ApproximateBuys
|
ApproximateBuys
|
||||||
{
|
{
|
||||||
@ -56,25 +54,22 @@ contract MooniswapSampler is
|
|||||||
uint256 numSamples = takerTokenAmounts.length;
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
|
|
||||||
address mooniswapTakerToken = takerToken == _getWethAddress() ? address(0) : takerToken;
|
|
||||||
address mooniswapMakerToken = makerToken == _getWethAddress() ? address(0) : makerToken;
|
|
||||||
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
uint256 buyAmount = sampleSingleSellFromMooniswapPool(
|
uint256 buyAmount = sampleSingleSellFromMooniswapPool(
|
||||||
registry,
|
registry,
|
||||||
mooniswapTakerToken,
|
takerToken,
|
||||||
mooniswapMakerToken,
|
makerToken,
|
||||||
takerTokenAmounts[i]
|
takerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
// Exit early if the amount is too high for the source to serve
|
makerTokenAmounts[i] = buyAmount;
|
||||||
if (buyAmount == 0) {
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
makerTokenAmounts[i] = buyAmount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pool = IMooniswap(
|
pool = IMooniswap(
|
||||||
IMooniswapRegistry(registry).pools(mooniswapTakerToken, mooniswapMakerToken)
|
IMooniswapRegistry(registry).pools(takerToken, makerToken)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,20 +134,17 @@ contract MooniswapSampler is
|
|||||||
uint256 numSamples = makerTokenAmounts.length;
|
uint256 numSamples = makerTokenAmounts.length;
|
||||||
takerTokenAmounts = new uint256[](numSamples);
|
takerTokenAmounts = new uint256[](numSamples);
|
||||||
|
|
||||||
address mooniswapTakerToken = takerToken == _getWethAddress() ? address(0) : takerToken;
|
|
||||||
address mooniswapMakerToken = makerToken == _getWethAddress() ? address(0) : makerToken;
|
|
||||||
|
|
||||||
takerTokenAmounts = _sampleApproximateBuys(
|
takerTokenAmounts = _sampleApproximateBuys(
|
||||||
ApproximateBuyQuoteOpts({
|
ApproximateBuyQuoteOpts({
|
||||||
makerTokenData: abi.encode(registry, mooniswapMakerToken),
|
makerTokenData: abi.encode(registry, makerToken),
|
||||||
takerTokenData: abi.encode(registry, mooniswapTakerToken),
|
takerTokenData: abi.encode(registry, takerToken),
|
||||||
getSellQuoteCallback: _sampleSellForApproximateBuyFromMooniswap
|
getSellQuoteCallback: _sampleSellForApproximateBuyFromMooniswap
|
||||||
}),
|
}),
|
||||||
makerTokenAmounts
|
makerTokenAmounts
|
||||||
);
|
);
|
||||||
|
|
||||||
pool = IMooniswap(
|
pool = IMooniswap(
|
||||||
IMooniswapRegistry(registry).pools(mooniswapTakerToken, mooniswapMakerToken)
|
IMooniswapRegistry(registry).pools(takerToken, makerToken)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,11 +20,9 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IShell.sol";
|
import "./interfaces/IShell.sol";
|
||||||
|
|
||||||
contract ShellSampler is
|
contract ShellSampler
|
||||||
DeploymentConstants
|
|
||||||
{
|
{
|
||||||
/// @dev Default gas limit for Shell calls.
|
/// @dev Default gas limit for Shell calls.
|
||||||
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
|
uint256 constant private DEFAULT_CALL_GAS = 300e3; // 300k
|
||||||
@ -58,6 +56,10 @@ contract ShellSampler is
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amount;
|
makerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -94,6 +96,10 @@ contract ShellSampler is
|
|||||||
returns (uint256 amount)
|
returns (uint256 amount)
|
||||||
{
|
{
|
||||||
takerTokenAmounts[i] = amount;
|
takerTokenAmounts[i] = amount;
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (takerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
/*
|
|
||||||
|
|
||||||
Copyright 2020 ZeroEx Intl.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
pragma solidity ^0.6;
|
|
||||||
pragma experimental ABIEncoderV2;
|
|
||||||
|
|
||||||
import "./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++) {
|
|
||||||
try
|
|
||||||
IUniswapV2Router01(router).getAmountsOut
|
|
||||||
{gas: SUSHISWAP_CALL_GAS}
|
|
||||||
(takerTokenAmounts[i], path)
|
|
||||||
returns (uint256[] memory amounts)
|
|
||||||
{
|
|
||||||
makerTokenAmounts[i] = amounts[path.length - 1];
|
|
||||||
} catch (bytes memory) {
|
|
||||||
// Swallow failures, leaving all results as zero.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @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++) {
|
|
||||||
try
|
|
||||||
IUniswapV2Router01(router).getAmountsIn
|
|
||||||
{gas: SUSHISWAP_CALL_GAS}
|
|
||||||
(makerTokenAmounts[i], path)
|
|
||||||
returns (uint256[] memory amounts)
|
|
||||||
{
|
|
||||||
takerTokenAmounts[i] = amounts[0];
|
|
||||||
} catch (bytes memory) {
|
|
||||||
// Swallow failures, leaving all results as zero.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,7 +20,6 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IUniswapExchangeQuotes.sol";
|
import "./interfaces/IUniswapExchangeQuotes.sol";
|
||||||
import "./SamplerUtils.sol";
|
import "./SamplerUtils.sol";
|
||||||
|
|
||||||
@ -37,21 +36,20 @@ interface IUniswapExchangeFactory {
|
|||||||
|
|
||||||
|
|
||||||
contract UniswapSampler is
|
contract UniswapSampler is
|
||||||
DeploymentConstants,
|
|
||||||
SamplerUtils
|
SamplerUtils
|
||||||
{
|
{
|
||||||
/// @dev Gas limit for Uniswap calls.
|
/// @dev Gas limit for Uniswap calls.
|
||||||
uint256 constant private UNISWAP_CALL_GAS = 150e3; // 150k
|
uint256 constant private UNISWAP_CALL_GAS = 150e3; // 150k
|
||||||
// @dev The BNB token is poisoned on uniswap v1.
|
|
||||||
address constant private BAD_MAKER_TOKEN = 0xB8c77482e45F1F44dE1745F52C74426C631bDD52;
|
|
||||||
|
|
||||||
/// @dev Sample sell quotes from Uniswap.
|
/// @dev Sample sell quotes from Uniswap.
|
||||||
|
/// @param router Address of the Uniswap Router
|
||||||
/// @param takerToken Address of the taker token (what to sell).
|
/// @param takerToken Address of the taker token (what to sell).
|
||||||
/// @param makerToken Address of the maker token (what to buy).
|
/// @param makerToken Address of the maker token (what to buy).
|
||||||
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
/// @param takerTokenAmounts Taker token sell amount for each sample.
|
||||||
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
/// @return makerTokenAmounts Maker amounts bought at each taker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleSellsFromUniswap(
|
function sampleSellsFromUniswap(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory takerTokenAmounts
|
uint256[] memory takerTokenAmounts
|
||||||
@ -63,23 +61,20 @@ contract UniswapSampler is
|
|||||||
_assertValidPair(makerToken, takerToken);
|
_assertValidPair(makerToken, takerToken);
|
||||||
uint256 numSamples = takerTokenAmounts.length;
|
uint256 numSamples = takerTokenAmounts.length;
|
||||||
makerTokenAmounts = new uint256[](numSamples);
|
makerTokenAmounts = new uint256[](numSamples);
|
||||||
if (makerToken == BAD_MAKER_TOKEN) {
|
|
||||||
// BNB is poisoned on v1. You can only sell to it.
|
IUniswapExchangeQuotes takerTokenExchange = takerToken == address(0) ?
|
||||||
return makerTokenAmounts;
|
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, takerToken);
|
||||||
}
|
IUniswapExchangeQuotes makerTokenExchange = makerToken == address(0) ?
|
||||||
IUniswapExchangeQuotes takerTokenExchange = takerToken == _getWethAddress() ?
|
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, makerToken);
|
||||||
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
|
|
||||||
IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWethAddress() ?
|
|
||||||
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
bool didSucceed = true;
|
bool didSucceed = true;
|
||||||
if (makerToken == _getWethAddress()) {
|
if (makerToken == address(0)) {
|
||||||
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
||||||
address(takerTokenExchange),
|
address(takerTokenExchange),
|
||||||
takerTokenExchange.getTokenToEthInputPrice.selector,
|
takerTokenExchange.getTokenToEthInputPrice.selector,
|
||||||
takerTokenAmounts[i]
|
takerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
} else if (takerToken == _getWethAddress()) {
|
} else if (takerToken == address(0)) {
|
||||||
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
(makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
||||||
address(makerTokenExchange),
|
address(makerTokenExchange),
|
||||||
makerTokenExchange.getEthToTokenInputPrice.selector,
|
makerTokenExchange.getEthToTokenInputPrice.selector,
|
||||||
@ -102,7 +97,8 @@ contract UniswapSampler is
|
|||||||
makerTokenAmounts[i] = 0;
|
makerTokenAmounts[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!didSucceed) {
|
// Break early if amounts are 0
|
||||||
|
if (!didSucceed || makerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,6 +111,7 @@ contract UniswapSampler is
|
|||||||
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
/// @return takerTokenAmounts Taker amounts sold at each maker token
|
||||||
/// amount.
|
/// amount.
|
||||||
function sampleBuysFromUniswap(
|
function sampleBuysFromUniswap(
|
||||||
|
address router,
|
||||||
address takerToken,
|
address takerToken,
|
||||||
address makerToken,
|
address makerToken,
|
||||||
uint256[] memory makerTokenAmounts
|
uint256[] memory makerTokenAmounts
|
||||||
@ -126,23 +123,20 @@ contract UniswapSampler is
|
|||||||
_assertValidPair(makerToken, takerToken);
|
_assertValidPair(makerToken, takerToken);
|
||||||
uint256 numSamples = makerTokenAmounts.length;
|
uint256 numSamples = makerTokenAmounts.length;
|
||||||
takerTokenAmounts = new uint256[](numSamples);
|
takerTokenAmounts = new uint256[](numSamples);
|
||||||
if (makerToken == BAD_MAKER_TOKEN) {
|
|
||||||
// BNB is poisoned on v1. You can only sell to it.
|
IUniswapExchangeQuotes takerTokenExchange = takerToken == address(0) ?
|
||||||
return takerTokenAmounts;
|
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, takerToken);
|
||||||
}
|
IUniswapExchangeQuotes makerTokenExchange = makerToken == address(0) ?
|
||||||
IUniswapExchangeQuotes takerTokenExchange = takerToken == _getWethAddress() ?
|
IUniswapExchangeQuotes(0) : _getUniswapExchange(router, makerToken);
|
||||||
IUniswapExchangeQuotes(0) : _getUniswapExchange(takerToken);
|
|
||||||
IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWethAddress() ?
|
|
||||||
IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken);
|
|
||||||
for (uint256 i = 0; i < numSamples; i++) {
|
for (uint256 i = 0; i < numSamples; i++) {
|
||||||
bool didSucceed = true;
|
bool didSucceed = true;
|
||||||
if (makerToken == _getWethAddress()) {
|
if (makerToken == address(0)) {
|
||||||
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
||||||
address(takerTokenExchange),
|
address(takerTokenExchange),
|
||||||
takerTokenExchange.getTokenToEthOutputPrice.selector,
|
takerTokenExchange.getTokenToEthOutputPrice.selector,
|
||||||
makerTokenAmounts[i]
|
makerTokenAmounts[i]
|
||||||
);
|
);
|
||||||
} else if (takerToken == _getWethAddress()) {
|
} else if (takerToken == address(0)) {
|
||||||
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
(takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction(
|
||||||
address(makerTokenExchange),
|
address(makerTokenExchange),
|
||||||
makerTokenExchange.getEthToTokenOutputPrice.selector,
|
makerTokenExchange.getEthToTokenOutputPrice.selector,
|
||||||
@ -165,7 +159,8 @@ contract UniswapSampler is
|
|||||||
takerTokenAmounts[i] = 0;
|
takerTokenAmounts[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!didSucceed) {
|
// Break early if amounts are 0
|
||||||
|
if (!didSucceed || takerTokenAmounts[i] == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -203,15 +198,16 @@ contract UniswapSampler is
|
|||||||
|
|
||||||
/// @dev Retrive an existing Uniswap exchange contract.
|
/// @dev Retrive an existing Uniswap exchange contract.
|
||||||
/// Throws if the exchange does not exist.
|
/// Throws if the exchange does not exist.
|
||||||
|
/// @param router Address of the Uniswap router.
|
||||||
/// @param tokenAddress Address of the token contract.
|
/// @param tokenAddress Address of the token contract.
|
||||||
/// @return exchange `IUniswapExchangeQuotes` for the token.
|
/// @return exchange `IUniswapExchangeQuotes` for the token.
|
||||||
function _getUniswapExchange(address tokenAddress)
|
function _getUniswapExchange(address router, address tokenAddress)
|
||||||
private
|
private
|
||||||
view
|
view
|
||||||
returns (IUniswapExchangeQuotes exchange)
|
returns (IUniswapExchangeQuotes exchange)
|
||||||
{
|
{
|
||||||
exchange = IUniswapExchangeQuotes(
|
exchange = IUniswapExchangeQuotes(
|
||||||
address(IUniswapExchangeFactory(_getUniswapExchangeFactoryAddress())
|
address(IUniswapExchangeFactory(router)
|
||||||
.getExchange(tokenAddress))
|
.getExchange(tokenAddress))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,10 @@
|
|||||||
pragma solidity ^0.6;
|
pragma solidity ^0.6;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "./DeploymentConstants.sol";
|
|
||||||
import "./interfaces/IUniswapV2Router01.sol";
|
import "./interfaces/IUniswapV2Router01.sol";
|
||||||
|
|
||||||
|
|
||||||
contract UniswapV2Sampler is
|
contract UniswapV2Sampler
|
||||||
DeploymentConstants
|
|
||||||
{
|
{
|
||||||
/// @dev Gas limit for UniswapV2 calls.
|
/// @dev Gas limit for UniswapV2 calls.
|
||||||
uint256 constant private UNISWAPV2_CALL_GAS = 150e3; // 150k
|
uint256 constant private UNISWAPV2_CALL_GAS = 150e3; // 150k
|
||||||
@ -55,6 +53,10 @@ contract UniswapV2Sampler is
|
|||||||
returns (uint256[] memory amounts)
|
returns (uint256[] memory amounts)
|
||||||
{
|
{
|
||||||
makerTokenAmounts[i] = amounts[path.length - 1];
|
makerTokenAmounts[i] = amounts[path.length - 1];
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (makerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
@ -87,6 +89,10 @@ contract UniswapV2Sampler is
|
|||||||
returns (uint256[] memory amounts)
|
returns (uint256[] memory amounts)
|
||||||
{
|
{
|
||||||
takerTokenAmounts[i] = amounts[0];
|
takerTokenAmounts[i] = amounts[0];
|
||||||
|
// Break early if there are 0 amounts
|
||||||
|
if (takerTokenAmounts[i] == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (bytes memory) {
|
} catch (bytes memory) {
|
||||||
// Swallow failures, leaving all results as zero.
|
// Swallow failures, leaving all results as zero.
|
||||||
break;
|
break;
|
||||||
|
@ -88,6 +88,25 @@ library LibDeterministicQuotes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contract TestDeploymentConstants {
|
||||||
|
|
||||||
|
// solhint-disable separate-by-one-line-in-contract
|
||||||
|
|
||||||
|
// Mainnet addresses ///////////////////////////////////////////////////////
|
||||||
|
/// @dev Mainnet address of the WETH contract.
|
||||||
|
address constant private WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
|
||||||
|
|
||||||
|
/// @dev Overridable way to get the WETH address.
|
||||||
|
/// @return wethAddress The WETH address.
|
||||||
|
function _getWethAddress()
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (address wethAddress)
|
||||||
|
{
|
||||||
|
return WETH_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
contract FailTrigger {
|
contract FailTrigger {
|
||||||
|
|
||||||
@ -109,7 +128,7 @@ contract FailTrigger {
|
|||||||
|
|
||||||
contract TestERC20BridgeSamplerUniswapExchange is
|
contract TestERC20BridgeSamplerUniswapExchange is
|
||||||
IUniswapExchangeQuotes,
|
IUniswapExchangeQuotes,
|
||||||
DeploymentConstants,
|
TestDeploymentConstants,
|
||||||
FailTrigger
|
FailTrigger
|
||||||
{
|
{
|
||||||
bytes32 constant private BASE_SALT = 0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab;
|
bytes32 constant private BASE_SALT = 0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab;
|
||||||
@ -198,7 +217,7 @@ contract TestERC20BridgeSamplerUniswapExchange is
|
|||||||
|
|
||||||
contract TestERC20BridgeSamplerUniswapV2Router01 is
|
contract TestERC20BridgeSamplerUniswapV2Router01 is
|
||||||
IUniswapV2Router01,
|
IUniswapV2Router01,
|
||||||
DeploymentConstants,
|
TestDeploymentConstants,
|
||||||
FailTrigger
|
FailTrigger
|
||||||
{
|
{
|
||||||
bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1;
|
bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1;
|
||||||
@ -249,7 +268,7 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
|
|||||||
|
|
||||||
// solhint-disable space-after-comma
|
// solhint-disable space-after-comma
|
||||||
contract TestERC20BridgeSamplerKyberNetwork is
|
contract TestERC20BridgeSamplerKyberNetwork is
|
||||||
DeploymentConstants,
|
TestDeploymentConstants,
|
||||||
FailTrigger
|
FailTrigger
|
||||||
{
|
{
|
||||||
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
|
bytes32 constant private SALT = 0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7;
|
||||||
@ -357,24 +376,6 @@ contract TestERC20BridgeSamplerKyberNetwork is
|
|||||||
toToken
|
toToken
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getKyberNetworkProxyAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address)
|
|
||||||
{
|
|
||||||
return address(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _getKyberHintHandlerAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address)
|
|
||||||
{
|
|
||||||
return address(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -502,54 +503,4 @@ contract TestERC20BridgeSampler is
|
|||||||
{
|
{
|
||||||
return LibDeterministicQuotes.getDeterministicTokenDecimals(tokenAddress);
|
return LibDeterministicQuotes.getDeterministicTokenDecimals(tokenAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overriden to point to a custom contract.
|
|
||||||
function _getEth2DaiAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address eth2daiAddress)
|
|
||||||
{
|
|
||||||
return address(eth2Dai);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overriden to point to a custom contract.
|
|
||||||
function _getUniswapExchangeFactoryAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address uniswapAddress)
|
|
||||||
{
|
|
||||||
return address(uniswap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overriden to point to a custom contract.
|
|
||||||
function _getUniswapV2Router01Address()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address uniswapV2RouterAddress)
|
|
||||||
{
|
|
||||||
return address(uniswapV2Router);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overriden to point to a custom contract.
|
|
||||||
function _getKyberNetworkProxyAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address kyberAddress)
|
|
||||||
{
|
|
||||||
return address(kyber);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overriden to point to a custom contract.
|
|
||||||
function _getKyberHintHandlerAddress()
|
|
||||||
override
|
|
||||||
internal
|
|
||||||
view
|
|
||||||
returns (address kyberAddress)
|
|
||||||
{
|
|
||||||
return address(kyber);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
|
"publicInterfaceContracts": "ERC20BridgeSampler,BalanceChecker,FakeTaker",
|
||||||
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
|
||||||
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DeploymentConstants|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json",
|
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalanceChecker|BalancerSampler|BancorSampler|CurveSampler|DODOSampler|DODOV2Sampler|DummyLiquidityProvider|ERC20BridgeSampler|Eth2DaiSampler|FakeTaker|IBalancer|IBancor|ICurve|IEth2Dai|IKyberNetwork|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler|UtilitySampler).json",
|
||||||
"postpublish": {
|
"postpublish": {
|
||||||
"assets": []
|
"assets": []
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
DEFAULT_INTERMEDIATE_TOKENS,
|
DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID,
|
||||||
DEFAULT_TOKEN_ADJACENCY_GRAPH,
|
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
|
||||||
} from './utils/market_operation_utils/constants';
|
} from './utils/market_operation_utils/constants';
|
||||||
|
|
||||||
const ETH_GAS_STATION_API_URL = 'https://ethgasstation.info/api/ethgasAPI.json';
|
const ETH_GAS_STATION_API_URL = 'https://ethgasstation.info/api/ethgasAPI.json';
|
||||||
@ -54,7 +54,7 @@ const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
|
|||||||
makerAssetOfferings: {},
|
makerAssetOfferings: {},
|
||||||
txOriginBlacklist: new Set(),
|
txOriginBlacklist: new Set(),
|
||||||
},
|
},
|
||||||
tokenAdjacencyGraph: DEFAULT_TOKEN_ADJACENCY_GRAPH,
|
tokenAdjacencyGraph: DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID[ChainId.Mainnet],
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS: ExchangeProxyContractOpts = {
|
const DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS: ExchangeProxyContractOpts = {
|
||||||
@ -112,7 +112,7 @@ export const constants = {
|
|||||||
ONE_SECOND_MS,
|
ONE_SECOND_MS,
|
||||||
ONE_MINUTE_MS,
|
ONE_MINUTE_MS,
|
||||||
DEFAULT_SWAP_QUOTER_OPTS,
|
DEFAULT_SWAP_QUOTER_OPTS,
|
||||||
DEFAULT_INTERMEDIATE_TOKENS,
|
DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID,
|
||||||
DEFAULT_SWAP_QUOTE_REQUEST_OPTS,
|
DEFAULT_SWAP_QUOTE_REQUEST_OPTS,
|
||||||
DEFAULT_EXCHANGE_PROXY_SWAP_QUOTE_GET_OPTS,
|
DEFAULT_EXCHANGE_PROXY_SWAP_QUOTE_GET_OPTS,
|
||||||
DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS,
|
DEFAULT_EXCHANGE_PROXY_EXTENSION_CONTRACT_OPTS,
|
||||||
|
@ -110,9 +110,11 @@ export {
|
|||||||
} from './types';
|
} from './types';
|
||||||
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
|
||||||
export {
|
export {
|
||||||
DEFAULT_TOKEN_ADJACENCY_GRAPH,
|
DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID,
|
||||||
DEFAULT_GAS_SCHEDULE,
|
DEFAULT_GAS_SCHEDULE,
|
||||||
SOURCE_FLAGS,
|
SOURCE_FLAGS,
|
||||||
|
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
|
SELL_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
} from './utils/market_operation_utils/constants';
|
} from './utils/market_operation_utils/constants';
|
||||||
export {
|
export {
|
||||||
Parameters,
|
Parameters,
|
||||||
@ -146,12 +148,7 @@ export {
|
|||||||
NativeLimitOrderFillData,
|
NativeLimitOrderFillData,
|
||||||
NativeFillData,
|
NativeFillData,
|
||||||
OptimizedMarketOrder,
|
OptimizedMarketOrder,
|
||||||
SnowSwapFillData,
|
|
||||||
SnowSwapInfo,
|
|
||||||
SourceQuoteOperation,
|
SourceQuoteOperation,
|
||||||
SushiSwapFillData,
|
|
||||||
SwerveFillData,
|
|
||||||
SwerveInfo,
|
|
||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './utils/market_operation_utils/types';
|
} from './utils/market_operation_utils/types';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ContractAddresses } from '@0x/contract-addresses';
|
import { ChainId, ContractAddresses } from '@0x/contract-addresses';
|
||||||
import { WETH9Contract } from '@0x/contracts-erc20';
|
import { IZeroExContract, WETH9Contract } from '@0x/contract-wrappers';
|
||||||
import { IZeroExContract, MultiplexFeatureContract } from '@0x/contracts-zero-ex';
|
import { MultiplexFeatureContract } from '@0x/contracts-zero-ex';
|
||||||
import {
|
import {
|
||||||
encodeAffiliateFeeTransformerData,
|
encodeAffiliateFeeTransformerData,
|
||||||
encodeCurveLiquidityProviderData,
|
encodeCurveLiquidityProviderData,
|
||||||
@ -34,6 +34,7 @@ import { assert } from '../utils/assert';
|
|||||||
import {
|
import {
|
||||||
CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID,
|
CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID,
|
||||||
MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID,
|
MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID,
|
||||||
|
NATIVE_FEE_TOKEN_BY_CHAIN_ID,
|
||||||
} from '../utils/market_operation_utils/constants';
|
} from '../utils/market_operation_utils/constants';
|
||||||
import { poolEncoder } from '../utils/market_operation_utils/orders';
|
import { poolEncoder } from '../utils/market_operation_utils/orders';
|
||||||
import {
|
import {
|
||||||
@ -62,10 +63,16 @@ import {
|
|||||||
// tslint:disable-next-line:custom-no-magic-numbers
|
// tslint:disable-next-line:custom-no-magic-numbers
|
||||||
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
|
const MAX_UINT256 = new BigNumber(2).pow(256).minus(1);
|
||||||
const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
|
const { NULL_ADDRESS, NULL_BYTES, ZERO_AMOUNT } = constants;
|
||||||
|
const PANCAKE_SWAP_FORKS = [ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.BakerySwap, ERC20BridgeSource.SushiSwap];
|
||||||
|
const DUMMY_WETH_CONTRACT = new WETH9Contract(NULL_ADDRESS, {
|
||||||
|
sendAsync(): void {
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
} as any);
|
||||||
|
|
||||||
export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
||||||
public readonly provider: ZeroExProvider;
|
public readonly provider: ZeroExProvider;
|
||||||
public readonly chainId: number;
|
public readonly chainId: ChainId;
|
||||||
public readonly transformerNonces: {
|
public readonly transformerNonces: {
|
||||||
wethTransformer: number;
|
wethTransformer: number;
|
||||||
payTakerTransformer: number;
|
payTakerTransformer: number;
|
||||||
@ -139,6 +146,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
|
|
||||||
// VIP routes.
|
// VIP routes.
|
||||||
if (
|
if (
|
||||||
|
this.chainId === ChainId.Mainnet &&
|
||||||
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.UniswapV2, ERC20BridgeSource.SushiSwap])
|
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.UniswapV2, ERC20BridgeSource.SushiSwap])
|
||||||
) {
|
) {
|
||||||
const source = quote.orders[0].source;
|
const source = quote.orders[0].source;
|
||||||
@ -167,7 +175,44 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.LiquidityProvider])) {
|
if (
|
||||||
|
this.chainId === ChainId.BSC &&
|
||||||
|
isDirectSwapCompatible(quote, optsWithDefaults, [
|
||||||
|
ERC20BridgeSource.PancakeSwap,
|
||||||
|
ERC20BridgeSource.BakerySwap,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
|
])
|
||||||
|
) {
|
||||||
|
const source = quote.orders[0].source;
|
||||||
|
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
|
||||||
|
return {
|
||||||
|
calldataHexString: this._exchangeProxy
|
||||||
|
.sellToPancakeSwap(
|
||||||
|
fillData.tokenAddressPath.map((a, i) => {
|
||||||
|
if (i === 0 && isFromETH) {
|
||||||
|
return ETH_TOKEN_ADDRESS;
|
||||||
|
}
|
||||||
|
if (i === fillData.tokenAddressPath.length - 1 && isToETH) {
|
||||||
|
return ETH_TOKEN_ADDRESS;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}),
|
||||||
|
sellAmount,
|
||||||
|
minBuyAmount,
|
||||||
|
PANCAKE_SWAP_FORKS.indexOf(source),
|
||||||
|
)
|
||||||
|
.getABIEncodedTransactionData(),
|
||||||
|
ethAmount: isFromETH ? sellAmount : ZERO_AMOUNT,
|
||||||
|
toAddress: this._exchangeProxy.address,
|
||||||
|
allowanceTarget: this._exchangeProxy.address,
|
||||||
|
gasOverhead: ZERO_AMOUNT,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.chainId === ChainId.Mainnet &&
|
||||||
|
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.LiquidityProvider])
|
||||||
|
) {
|
||||||
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<LiquidityProviderFillData>).fillData;
|
const fillData = (quote.orders[0] as OptimizedMarketBridgeOrder<LiquidityProviderFillData>).fillData;
|
||||||
const target = fillData.poolAddress;
|
const target = fillData.poolAddress;
|
||||||
return {
|
return {
|
||||||
@ -189,7 +234,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve, ERC20BridgeSource.Swerve])) {
|
if (
|
||||||
|
this.chainId === ChainId.Mainnet &&
|
||||||
|
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Curve, ERC20BridgeSource.Swerve])
|
||||||
|
) {
|
||||||
const fillData = quote.orders[0].fills[0].fillData as CurveFillData;
|
const fillData = quote.orders[0].fills[0].fillData as CurveFillData;
|
||||||
return {
|
return {
|
||||||
calldataHexString: this._exchangeProxy
|
calldataHexString: this._exchangeProxy
|
||||||
@ -215,7 +263,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Mooniswap])) {
|
if (
|
||||||
|
this.chainId === ChainId.Mainnet &&
|
||||||
|
isDirectSwapCompatible(quote, optsWithDefaults, [ERC20BridgeSource.Mooniswap])
|
||||||
|
) {
|
||||||
const fillData = quote.orders[0].fills[0].fillData as MooniswapFillData;
|
const fillData = quote.orders[0].fills[0].fillData as MooniswapFillData;
|
||||||
return {
|
return {
|
||||||
calldataHexString: this._exchangeProxy
|
calldataHexString: this._exchangeProxy
|
||||||
@ -236,7 +287,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMultiplexBatchFillCompatible(quote, optsWithDefaults)) {
|
if (this.chainId === ChainId.Mainnet && isMultiplexBatchFillCompatible(quote, optsWithDefaults)) {
|
||||||
return {
|
return {
|
||||||
calldataHexString: this._encodeMultiplexBatchFillCalldata(quote),
|
calldataHexString: this._encodeMultiplexBatchFillCalldata(quote),
|
||||||
ethAmount,
|
ethAmount,
|
||||||
@ -245,7 +296,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
gasOverhead: ZERO_AMOUNT,
|
gasOverhead: ZERO_AMOUNT,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (isMultiplexMultiHopFillCompatible(quote, optsWithDefaults)) {
|
if (this.chainId === ChainId.Mainnet && isMultiplexMultiHopFillCompatible(quote, optsWithDefaults)) {
|
||||||
return {
|
return {
|
||||||
calldataHexString: this._encodeMultiplexMultiHopFillCalldata(quote, optsWithDefaults),
|
calldataHexString: this._encodeMultiplexMultiHopFillCalldata(quote, optsWithDefaults),
|
||||||
ethAmount,
|
ethAmount,
|
||||||
@ -317,7 +368,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
transforms.push({
|
transforms.push({
|
||||||
deploymentNonce: this.transformerNonces.wethTransformer,
|
deploymentNonce: this.transformerNonces.wethTransformer,
|
||||||
data: encodeWethTransformerData({
|
data: encodeWethTransformerData({
|
||||||
token: this.contractAddresses.etherToken,
|
token: NATIVE_FEE_TOKEN_BY_CHAIN_ID[this.chainId],
|
||||||
amount: MAX_UINT256,
|
amount: MAX_UINT256,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@ -491,11 +542,10 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _encodeMultiplexMultiHopFillCalldata(quote: SwapQuote, opts: ExchangeProxyContractOpts): string {
|
private _encodeMultiplexMultiHopFillCalldata(quote: SwapQuote, opts: ExchangeProxyContractOpts): string {
|
||||||
const weth = new WETH9Contract(NULL_ADDRESS, this.provider);
|
|
||||||
const wrappedMultiHopCalls = [];
|
const wrappedMultiHopCalls = [];
|
||||||
if (opts.isFromETH) {
|
if (opts.isFromETH) {
|
||||||
wrappedMultiHopCalls.push({
|
wrappedMultiHopCalls.push({
|
||||||
selector: weth.getSelector('deposit'),
|
selector: DUMMY_WETH_CONTRACT.getSelector('deposit'),
|
||||||
data: NULL_BYTES,
|
data: NULL_BYTES,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -532,7 +582,7 @@ export class ExchangeProxySwapQuoteConsumer implements SwapQuoteConsumerBase {
|
|||||||
}
|
}
|
||||||
if (opts.isToETH) {
|
if (opts.isToETH) {
|
||||||
wrappedMultiHopCalls.push({
|
wrappedMultiHopCalls.push({
|
||||||
selector: weth.getSelector('withdraw'),
|
selector: DUMMY_WETH_CONTRACT.getSelector('withdraw'),
|
||||||
data: NULL_BYTES,
|
data: NULL_BYTES,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { FillQuoteTransformerData, FillQuoteTransformerOrderType } from '@0x/pro
|
|||||||
import { AffiliateFeeType, ExchangeProxyContractOpts, MarketBuySwapQuote, MarketOperation, SwapQuote } from '../types';
|
import { AffiliateFeeType, ExchangeProxyContractOpts, MarketBuySwapQuote, MarketOperation, SwapQuote } from '../types';
|
||||||
import {
|
import {
|
||||||
createBridgeDataForBridgeOrder,
|
createBridgeDataForBridgeOrder,
|
||||||
getERC20BridgeSourceToBridgeSource,
|
getErc20BridgeSourceToBridgeSource,
|
||||||
} from '../utils/market_operation_utils/orders';
|
} from '../utils/market_operation_utils/orders';
|
||||||
import {
|
import {
|
||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
@ -128,7 +128,7 @@ export function getFQTTransformerDataFromOptimizedOrders(
|
|||||||
bridgeData: createBridgeDataForBridgeOrder(order),
|
bridgeData: createBridgeDataForBridgeOrder(order),
|
||||||
makerTokenAmount: order.makerAmount,
|
makerTokenAmount: order.makerAmount,
|
||||||
takerTokenAmount: order.takerAmount,
|
takerTokenAmount: order.takerAmount,
|
||||||
source: getERC20BridgeSourceToBridgeSource(order.source),
|
source: getErc20BridgeSourceToBridgeSource(order.source),
|
||||||
});
|
});
|
||||||
} else if (isOptimizedLimitOrder(order)) {
|
} else if (isOptimizedLimitOrder(order)) {
|
||||||
fqtData.limitOrders.push({
|
fqtData.limitOrders.push({
|
||||||
|
@ -132,6 +132,7 @@ export class SwapQuoter {
|
|||||||
|
|
||||||
this._marketOperationUtils = new MarketOperationUtils(
|
this._marketOperationUtils = new MarketOperationUtils(
|
||||||
new DexOrderSampler(
|
new DexOrderSampler(
|
||||||
|
this.chainId,
|
||||||
samplerContract,
|
samplerContract,
|
||||||
samplerOverrides,
|
samplerOverrides,
|
||||||
undefined, // balancer pool cache
|
undefined, // balancer pool cache
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
|
import { ChainId } from '@0x/contract-addresses';
|
||||||
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
BAKERYSWAP_ROUTER_BY_CHAIN_ID,
|
||||||
|
BELT_BSC_INFOS,
|
||||||
|
CRYPTO_COM_ROUTER_BY_CHAIN_ID,
|
||||||
|
ELLIPSIS_BSC_INFOS,
|
||||||
KYBER_BRIDGED_LIQUIDITY_PREFIX,
|
KYBER_BRIDGED_LIQUIDITY_PREFIX,
|
||||||
MAINNET_CURVE_INFOS,
|
MAINNET_CURVE_INFOS,
|
||||||
MAINNET_SHELL_POOLS,
|
|
||||||
MAINNET_SNOWSWAP_INFOS,
|
MAINNET_SNOWSWAP_INFOS,
|
||||||
MAINNET_SWERVE_INFOS,
|
MAINNET_SWERVE_INFOS,
|
||||||
MAX_DODOV2_POOLS_QUERIED,
|
MAX_DODOV2_POOLS_QUERIED,
|
||||||
MAX_KYBER_RESERVES_QUERIED,
|
MAX_KYBER_RESERVES_QUERIED,
|
||||||
|
NERVE_BSC_INFOS,
|
||||||
|
NULL_ADDRESS,
|
||||||
|
PANCAKESWAP_ROUTER_BY_CHAIN_ID,
|
||||||
|
SHELL_POOLS_BY_CHAIN_ID,
|
||||||
|
SUSHISWAP_ROUTER_BY_CHAIN_ID,
|
||||||
|
UNISWAPV2_ROUTER_BY_CHAIN_ID,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
import { CurveInfo, SnowSwapInfo, SwerveInfo } from './types';
|
import { CurveInfo, ERC20BridgeSource } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter Kyber reserves which should not be used (0xbb bridged reserves)
|
* Filter Kyber reserves which should not be used (0xbb bridged reserves)
|
||||||
@ -19,6 +29,11 @@ export function isAllowedKyberReserveId(reserveId: string): boolean {
|
|||||||
return reserveId !== NULL_BYTES && !reserveId.startsWith(KYBER_BRIDGED_LIQUIDITY_PREFIX);
|
return reserveId !== NULL_BYTES && !reserveId.startsWith(KYBER_BRIDGED_LIQUIDITY_PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable-next-line: completed-docs ban-types
|
||||||
|
export function isValidAddress(address: string | String): address is string {
|
||||||
|
return (typeof address === 'string' || address instanceof String) && address.toString() !== NULL_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the offsets to be used to discover Kyber reserves
|
* Returns the offsets to be used to discover Kyber reserves
|
||||||
*/
|
*/
|
||||||
@ -36,14 +51,20 @@ export function getDodoV2Offsets(): BigNumber[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
// tslint:disable completed-docs
|
||||||
export function getShellsForPair(takerToken: string, makerToken: string): string[] {
|
export function getShellsForPair(chainId: ChainId, takerToken: string, makerToken: string): string[] {
|
||||||
return Object.values(MAINNET_SHELL_POOLS)
|
if (chainId !== ChainId.Mainnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.values(SHELL_POOLS_BY_CHAIN_ID[chainId])
|
||||||
.filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)))
|
.filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)))
|
||||||
.map(i => i.poolAddress);
|
.map(i => i.poolAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
// tslint:disable completed-docs
|
||||||
export function getCurveInfosForPair(takerToken: string, makerToken: string): CurveInfo[] {
|
export function getCurveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.Mainnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return Object.values(MAINNET_CURVE_INFOS).filter(c =>
|
return Object.values(MAINNET_CURVE_INFOS).filter(c =>
|
||||||
[makerToken, takerToken].every(
|
[makerToken, takerToken].every(
|
||||||
t =>
|
t =>
|
||||||
@ -53,7 +74,10 @@ export function getCurveInfosForPair(takerToken: string, makerToken: string): Cu
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSwerveInfosForPair(takerToken: string, makerToken: string): SwerveInfo[] {
|
export function getSwerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.Mainnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return Object.values(MAINNET_SWERVE_INFOS).filter(c =>
|
return Object.values(MAINNET_SWERVE_INFOS).filter(c =>
|
||||||
[makerToken, takerToken].every(
|
[makerToken, takerToken].every(
|
||||||
t =>
|
t =>
|
||||||
@ -63,7 +87,10 @@ export function getSwerveInfosForPair(takerToken: string, makerToken: string): S
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSnowSwapInfosForPair(takerToken: string, makerToken: string): SnowSwapInfo[] {
|
export function getSnowSwapInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.Mainnet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
return Object.values(MAINNET_SNOWSWAP_INFOS).filter(c =>
|
return Object.values(MAINNET_SNOWSWAP_INFOS).filter(c =>
|
||||||
[makerToken, takerToken].every(
|
[makerToken, takerToken].every(
|
||||||
t =>
|
t =>
|
||||||
@ -72,3 +99,107 @@ export function getSnowSwapInfosForPair(takerToken: string, makerToken: string):
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getNerveInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.BSC) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.values(NERVE_BSC_INFOS).filter(c =>
|
||||||
|
[makerToken, takerToken].every(
|
||||||
|
t =>
|
||||||
|
(c.tokens.includes(t) && c.metaToken === undefined) ||
|
||||||
|
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getBeltInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.BSC) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.values(BELT_BSC_INFOS).filter(c =>
|
||||||
|
[makerToken, takerToken].every(
|
||||||
|
t =>
|
||||||
|
(c.tokens.includes(t) && c.metaToken === undefined) ||
|
||||||
|
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEllipsisInfosForPair(chainId: ChainId, takerToken: string, makerToken: string): CurveInfo[] {
|
||||||
|
if (chainId !== ChainId.BSC) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return Object.values(ELLIPSIS_BSC_INFOS).filter(c =>
|
||||||
|
[makerToken, takerToken].every(
|
||||||
|
t =>
|
||||||
|
(c.tokens.includes(t) && c.metaToken === undefined) ||
|
||||||
|
(c.tokens.includes(t) && c.metaToken !== undefined && [makerToken, takerToken].includes(c.metaToken)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCurveLikeInfosForPair(
|
||||||
|
chainId: ChainId,
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
source:
|
||||||
|
| ERC20BridgeSource.Curve
|
||||||
|
| ERC20BridgeSource.Swerve
|
||||||
|
| ERC20BridgeSource.SnowSwap
|
||||||
|
| ERC20BridgeSource.Nerve
|
||||||
|
| ERC20BridgeSource.Belt
|
||||||
|
| ERC20BridgeSource.Ellipsis,
|
||||||
|
): CurveInfo[] {
|
||||||
|
switch (source) {
|
||||||
|
case ERC20BridgeSource.Curve:
|
||||||
|
return getCurveInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
case ERC20BridgeSource.Swerve:
|
||||||
|
return getSwerveInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
case ERC20BridgeSource.SnowSwap:
|
||||||
|
return getSnowSwapInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
case ERC20BridgeSource.Nerve:
|
||||||
|
return getNerveInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
case ERC20BridgeSource.Belt:
|
||||||
|
return getBeltInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
case ERC20BridgeSource.Ellipsis:
|
||||||
|
return getEllipsisInfosForPair(chainId, takerToken, makerToken);
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown Curve like source ${source}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function uniswapV2LikeRouterAddress(
|
||||||
|
chainId: ChainId,
|
||||||
|
source:
|
||||||
|
| ERC20BridgeSource.UniswapV2
|
||||||
|
| ERC20BridgeSource.SushiSwap
|
||||||
|
| ERC20BridgeSource.CryptoCom
|
||||||
|
| ERC20BridgeSource.PancakeSwap
|
||||||
|
| ERC20BridgeSource.BakerySwap,
|
||||||
|
): string {
|
||||||
|
switch (source) {
|
||||||
|
case ERC20BridgeSource.UniswapV2:
|
||||||
|
return UNISWAPV2_ROUTER_BY_CHAIN_ID[chainId];
|
||||||
|
case ERC20BridgeSource.SushiSwap:
|
||||||
|
return SUSHISWAP_ROUTER_BY_CHAIN_ID[chainId];
|
||||||
|
case ERC20BridgeSource.CryptoCom:
|
||||||
|
return CRYPTO_COM_ROUTER_BY_CHAIN_ID[chainId];
|
||||||
|
case ERC20BridgeSource.PancakeSwap:
|
||||||
|
return PANCAKESWAP_ROUTER_BY_CHAIN_ID[chainId];
|
||||||
|
case ERC20BridgeSource.BakerySwap:
|
||||||
|
return BAKERYSWAP_ROUTER_BY_CHAIN_ID[chainId];
|
||||||
|
default:
|
||||||
|
throw new Error(`Unknown UniswapV2 like source ${source}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BAD_TOKENS_BY_SOURCE: Partial<{ [key in ERC20BridgeSource]: string[] }> = {
|
||||||
|
[ERC20BridgeSource.Uniswap]: [
|
||||||
|
'0xb8c77482e45f1f44de1745f52c74426c631bdd52', // BNB
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function isBadTokenForSource(token: string, source: ERC20BridgeSource): boolean {
|
||||||
|
return (BAD_TOKENS_BY_SOURCE[source] || []).includes(token.toLowerCase());
|
||||||
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ChainId } from '@0x/contract-addresses';
|
||||||
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
import { FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
||||||
import { BigNumber } from '@0x/utils';
|
import { BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
@ -14,11 +15,10 @@ import {
|
|||||||
FeeSchedule,
|
FeeSchedule,
|
||||||
FillData,
|
FillData,
|
||||||
GetMarketOrdersOpts,
|
GetMarketOrdersOpts,
|
||||||
|
KyberSamplerOpts,
|
||||||
LiquidityProviderFillData,
|
LiquidityProviderFillData,
|
||||||
LiquidityProviderRegistry,
|
LiquidityProviderRegistry,
|
||||||
MultiHopFillData,
|
MultiHopFillData,
|
||||||
SnowSwapFillData,
|
|
||||||
SushiSwapFillData,
|
|
||||||
TokenAdjacencyGraph,
|
TokenAdjacencyGraph,
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './types';
|
} from './types';
|
||||||
@ -38,10 +38,25 @@ export const NULL_BYTES = '0x';
|
|||||||
export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||||
export const COMPARISON_PRICE_DECIMALS = 10;
|
export const COMPARISON_PRICE_DECIMALS = 10;
|
||||||
|
|
||||||
|
function valueByChainId<T>(rest: Partial<{ [key in ChainId]: T }>, defaultValue: T): { [key in ChainId]: T } {
|
||||||
|
// TODO I don't like this but iterating through enums is weird
|
||||||
|
return {
|
||||||
|
[ChainId.Mainnet]: defaultValue,
|
||||||
|
[ChainId.Ropsten]: defaultValue,
|
||||||
|
[ChainId.Rinkeby]: defaultValue,
|
||||||
|
[ChainId.Kovan]: defaultValue,
|
||||||
|
[ChainId.Ganache]: defaultValue,
|
||||||
|
[ChainId.BSC]: defaultValue,
|
||||||
|
...(rest || {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid sources for market sell.
|
* Valid sources for market sell.
|
||||||
*/
|
*/
|
||||||
export const SELL_SOURCE_FILTER = new SourceFilters([
|
export const SELL_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: new SourceFilters([
|
||||||
ERC20BridgeSource.Native,
|
ERC20BridgeSource.Native,
|
||||||
ERC20BridgeSource.Uniswap,
|
ERC20BridgeSource.Uniswap,
|
||||||
ERC20BridgeSource.UniswapV2,
|
ERC20BridgeSource.UniswapV2,
|
||||||
@ -63,12 +78,34 @@ export const SELL_SOURCE_FILTER = new SourceFilters([
|
|||||||
ERC20BridgeSource.LiquidityProvider,
|
ERC20BridgeSource.LiquidityProvider,
|
||||||
ERC20BridgeSource.CryptoCom,
|
ERC20BridgeSource.CryptoCom,
|
||||||
ERC20BridgeSource.Linkswap,
|
ERC20BridgeSource.Linkswap,
|
||||||
]);
|
]),
|
||||||
|
[ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Kovan]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Ganache]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.BSC]: new SourceFilters([
|
||||||
|
ERC20BridgeSource.BakerySwap,
|
||||||
|
ERC20BridgeSource.Belt,
|
||||||
|
ERC20BridgeSource.Dodo,
|
||||||
|
ERC20BridgeSource.DodoV2,
|
||||||
|
ERC20BridgeSource.Ellipsis,
|
||||||
|
ERC20BridgeSource.Mooniswap,
|
||||||
|
ERC20BridgeSource.MultiHop,
|
||||||
|
ERC20BridgeSource.Nerve,
|
||||||
|
ERC20BridgeSource.PancakeSwap,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
|
||||||
|
new SourceFilters([]),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valid sources for market buy.
|
* Valid sources for market buy.
|
||||||
*/
|
*/
|
||||||
export const BUY_SOURCE_FILTER = new SourceFilters([
|
export const BUY_SOURCE_FILTER_BY_CHAIN_ID = valueByChainId<SourceFilters>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: new SourceFilters([
|
||||||
ERC20BridgeSource.Native,
|
ERC20BridgeSource.Native,
|
||||||
ERC20BridgeSource.Uniswap,
|
ERC20BridgeSource.Uniswap,
|
||||||
ERC20BridgeSource.UniswapV2,
|
ERC20BridgeSource.UniswapV2,
|
||||||
@ -90,7 +127,26 @@ export const BUY_SOURCE_FILTER = new SourceFilters([
|
|||||||
ERC20BridgeSource.LiquidityProvider,
|
ERC20BridgeSource.LiquidityProvider,
|
||||||
ERC20BridgeSource.CryptoCom,
|
ERC20BridgeSource.CryptoCom,
|
||||||
ERC20BridgeSource.Linkswap,
|
ERC20BridgeSource.Linkswap,
|
||||||
]);
|
]),
|
||||||
|
[ChainId.Ropsten]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Rinkeby]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Kovan]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.Ganache]: new SourceFilters([ERC20BridgeSource.Native]),
|
||||||
|
[ChainId.BSC]: new SourceFilters([
|
||||||
|
ERC20BridgeSource.BakerySwap,
|
||||||
|
ERC20BridgeSource.Belt,
|
||||||
|
ERC20BridgeSource.Dodo,
|
||||||
|
ERC20BridgeSource.DodoV2,
|
||||||
|
ERC20BridgeSource.Ellipsis,
|
||||||
|
ERC20BridgeSource.Mooniswap,
|
||||||
|
ERC20BridgeSource.MultiHop,
|
||||||
|
ERC20BridgeSource.Nerve,
|
||||||
|
ERC20BridgeSource.PancakeSwap,
|
||||||
|
ERC20BridgeSource.SushiSwap,
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
new SourceFilters([]),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 0x Protocol Fee Multiplier
|
* 0x Protocol Fee Multiplier
|
||||||
@ -100,7 +156,13 @@ export const PROTOCOL_FEE_MULTIPLIER = new BigNumber(70000);
|
|||||||
/**
|
/**
|
||||||
* Sources to poll for ETH fee price estimates.
|
* Sources to poll for ETH fee price estimates.
|
||||||
*/
|
*/
|
||||||
export const FEE_QUOTE_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.UniswapV2];
|
export const FEE_QUOTE_SOURCES_BY_CHAIN_ID = valueByChainId<ERC20BridgeSource[]>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: [ERC20BridgeSource.Uniswap, ERC20BridgeSource.UniswapV2],
|
||||||
|
[ChainId.BSC]: [ERC20BridgeSource.PancakeSwap, ERC20BridgeSource.Mooniswap, ERC20BridgeSource.SushiSwap],
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
// HACK(mzhu25): Limit and RFQ orders need to be treated as different sources
|
// HACK(mzhu25): Limit and RFQ orders need to be treated as different sources
|
||||||
// when computing the exchange proxy gas overhead.
|
// when computing the exchange proxy gas overhead.
|
||||||
@ -173,7 +235,7 @@ export const TOKENS = {
|
|||||||
...MIRROR_WRAPPED_TOKENS,
|
...MIRROR_WRAPPED_TOKENS,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const POOLS = {
|
export const CURVE_POOLS = {
|
||||||
curve_compound: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56', // 0.Compound
|
curve_compound: '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56', // 0.Compound
|
||||||
// 1.USDT is dead
|
// 1.USDT is dead
|
||||||
curve_PAX: '0x06364f10b501e868329afbc005b3492902d6c763', // 2.PAX
|
curve_PAX: '0x06364f10b501e868329afbc005b3492902d6c763', // 2.PAX
|
||||||
@ -202,11 +264,26 @@ export const POOLS = {
|
|||||||
curve_aave: '0xdebf20617708857ebe4f679508e7b7863a8a8eee', // 25.aave
|
curve_aave: '0xdebf20617708857ebe4f679508e7b7863a8a8eee', // 25.aave
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_INTERMEDIATE_TOKENS = [TOKENS.WETH, TOKENS.USDT, TOKENS.DAI, TOKENS.USDC, TOKENS.WBTC];
|
export const DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID = valueByChainId<string[]>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: [TOKENS.WETH, TOKENS.USDT, TOKENS.DAI, TOKENS.USDC, TOKENS.WBTC],
|
||||||
|
[ChainId.BSC]: [
|
||||||
|
'0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', // WBNB
|
||||||
|
'0xe9e7cea3dedca5984780bafc599bd69add087d56', // BUSD
|
||||||
|
'0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3', // DAI
|
||||||
|
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC
|
||||||
|
'0x2170ed0880ac9a755fd29b2688956bd959f933f8', // ETH
|
||||||
|
'0x55d398326f99059ff775485246999027b3197955', // BUSD-T
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
export const DEFAULT_TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = new TokenAdjacencyGraphBuilder({
|
export const DEFAULT_TOKEN_ADJACENCY_GRAPH_BY_CHAIN_ID = valueByChainId<TokenAdjacencyGraph>(
|
||||||
default: DEFAULT_INTERMEDIATE_TOKENS,
|
{
|
||||||
})
|
[ChainId.Mainnet]: new TokenAdjacencyGraphBuilder({
|
||||||
|
default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.Mainnet],
|
||||||
|
})
|
||||||
// Mirror Protocol
|
// Mirror Protocol
|
||||||
.tap(builder => {
|
.tap(builder => {
|
||||||
builder
|
builder
|
||||||
@ -216,7 +293,23 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = new TokenAdjac
|
|||||||
Object.values(MIRROR_WRAPPED_TOKENS).forEach(t => builder.add(t, TOKENS.UST));
|
Object.values(MIRROR_WRAPPED_TOKENS).forEach(t => builder.add(t, TOKENS.UST));
|
||||||
})
|
})
|
||||||
// Build
|
// Build
|
||||||
.build();
|
.build(),
|
||||||
|
[ChainId.BSC]: new TokenAdjacencyGraphBuilder({
|
||||||
|
default: DEFAULT_INTERMEDIATE_TOKENS_BY_CHAIN_ID[ChainId.BSC],
|
||||||
|
}).build(),
|
||||||
|
},
|
||||||
|
new TokenAdjacencyGraphBuilder({ default: [] }).build(),
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NATIVE_FEE_TOKEN_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: TOKENS.WETH,
|
||||||
|
[ChainId.BSC]: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', // WBNB
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NATIVE_FEE_TOKEN_AMOUNT_BY_CHAIN_ID = valueByChainId({}, ONE_ETHER);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mainnet Curve configuration
|
* Mainnet Curve configuration
|
||||||
@ -224,147 +317,147 @@ export const DEFAULT_TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = new TokenAdjac
|
|||||||
* I.e DaiUsdc curve has DAI as index 0 and USDC as index 1
|
* I.e DaiUsdc curve has DAI as index 0 and USDC as index 1
|
||||||
*/
|
*/
|
||||||
export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
||||||
[POOLS.curve_compound]: {
|
[CURVE_POOLS.curve_compound]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.get_dx_underlying,
|
||||||
poolAddress: POOLS.curve_compound,
|
poolAddress: CURVE_POOLS.curve_compound,
|
||||||
tokens: [TOKENS.DAI, TOKENS.USDC],
|
tokens: [TOKENS.DAI, TOKENS.USDC],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_PAX]: {
|
[CURVE_POOLS.curve_PAX]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_PAX,
|
poolAddress: CURVE_POOLS.curve_PAX,
|
||||||
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.PAX],
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.PAX],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_sUSD]: {
|
[CURVE_POOLS.curve_sUSD]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_sUSD,
|
poolAddress: CURVE_POOLS.curve_sUSD,
|
||||||
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD],
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_renBTC]: {
|
[CURVE_POOLS.curve_renBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_renBTC,
|
poolAddress: CURVE_POOLS.curve_renBTC,
|
||||||
tokens: [TOKENS.RenBTC, TOKENS.WBTC],
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_sBTC]: {
|
[CURVE_POOLS.curve_sBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_sBTC,
|
poolAddress: CURVE_POOLS.curve_sBTC,
|
||||||
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_HBTC]: {
|
[CURVE_POOLS.curve_HBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_HBTC,
|
poolAddress: CURVE_POOLS.curve_HBTC,
|
||||||
tokens: [TOKENS.hBTC, TOKENS.WBTC],
|
tokens: [TOKENS.hBTC, TOKENS.WBTC],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_TRI]: {
|
[CURVE_POOLS.curve_TRI]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_TRI,
|
poolAddress: CURVE_POOLS.curve_TRI,
|
||||||
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_GUSD]: {
|
[CURVE_POOLS.curve_GUSD]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_GUSD,
|
poolAddress: CURVE_POOLS.curve_GUSD,
|
||||||
tokens: [TOKENS.GUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.GUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.GUSD,
|
metaToken: TOKENS.GUSD,
|
||||||
},
|
},
|
||||||
[POOLS.curve_HUSD]: {
|
[CURVE_POOLS.curve_HUSD]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_HUSD,
|
poolAddress: CURVE_POOLS.curve_HUSD,
|
||||||
tokens: [TOKENS.HUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.HUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.HUSD,
|
metaToken: TOKENS.HUSD,
|
||||||
},
|
},
|
||||||
[POOLS.curve_USDN]: {
|
[CURVE_POOLS.curve_USDN]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_USDN,
|
poolAddress: CURVE_POOLS.curve_USDN,
|
||||||
tokens: [TOKENS.USDN, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.USDN, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.USDN,
|
metaToken: TOKENS.USDN,
|
||||||
},
|
},
|
||||||
[POOLS.curve_mUSD]: {
|
[CURVE_POOLS.curve_mUSD]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_mUSD,
|
poolAddress: CURVE_POOLS.curve_mUSD,
|
||||||
tokens: [TOKENS.mUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.mUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.mUSD,
|
metaToken: TOKENS.mUSD,
|
||||||
},
|
},
|
||||||
[POOLS.curve_tBTC]: {
|
[CURVE_POOLS.curve_tBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_tBTC,
|
poolAddress: CURVE_POOLS.curve_tBTC,
|
||||||
tokens: [TOKENS.tBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.tBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
metaToken: TOKENS.tBTC,
|
metaToken: TOKENS.tBTC,
|
||||||
},
|
},
|
||||||
[POOLS.curve_dUSD]: {
|
[CURVE_POOLS.curve_dUSD]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_dUSD,
|
poolAddress: CURVE_POOLS.curve_dUSD,
|
||||||
tokens: [TOKENS.dUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.dUSD, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.dUSD,
|
metaToken: TOKENS.dUSD,
|
||||||
},
|
},
|
||||||
[POOLS.curve_pBTC]: {
|
[CURVE_POOLS.curve_pBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_pBTC,
|
poolAddress: CURVE_POOLS.curve_pBTC,
|
||||||
tokens: [TOKENS.pBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.pBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
metaToken: TOKENS.pBTC,
|
metaToken: TOKENS.pBTC,
|
||||||
},
|
},
|
||||||
[POOLS.curve_bBTC]: {
|
[CURVE_POOLS.curve_bBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_bBTC,
|
poolAddress: CURVE_POOLS.curve_bBTC,
|
||||||
tokens: [TOKENS.bBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.bBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
metaToken: TOKENS.bBTC,
|
metaToken: TOKENS.bBTC,
|
||||||
},
|
},
|
||||||
[POOLS.curve_oBTC]: {
|
[CURVE_POOLS.curve_oBTC]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_oBTC,
|
poolAddress: CURVE_POOLS.curve_oBTC,
|
||||||
tokens: [TOKENS.oBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.oBTC, TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
metaToken: TOKENS.oBTC,
|
metaToken: TOKENS.oBTC,
|
||||||
},
|
},
|
||||||
[POOLS.curve_UST]: {
|
[CURVE_POOLS.curve_UST]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_UST,
|
poolAddress: CURVE_POOLS.curve_UST,
|
||||||
tokens: [TOKENS.UST, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.UST, TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: TOKENS.UST,
|
metaToken: TOKENS.UST,
|
||||||
},
|
},
|
||||||
[POOLS.curve_eurs]: {
|
[CURVE_POOLS.curve_eurs]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_eurs,
|
poolAddress: CURVE_POOLS.curve_eurs,
|
||||||
tokens: [TOKENS.EURS, TOKENS.sEUR],
|
tokens: [TOKENS.EURS, TOKENS.sEUR],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
@ -376,19 +469,19 @@ export const MAINNET_CURVE_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
// tokens: [TOKENS.ETH, TOKENS.sETH],
|
// tokens: [TOKENS.ETH, TOKENS.sETH],
|
||||||
// metaToken: undefined,
|
// metaToken: undefined,
|
||||||
// },
|
// },
|
||||||
[POOLS.curve_aave]: {
|
[CURVE_POOLS.curve_aave]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_aave,
|
poolAddress: CURVE_POOLS.curve_aave,
|
||||||
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
tokens: [TOKENS.DAI, TOKENS.USDC, TOKENS.USDT],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
[POOLS.curve_aave]: {
|
[CURVE_POOLS.curve_aave]: {
|
||||||
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
poolAddress: POOLS.curve_aave,
|
poolAddress: CURVE_POOLS.curve_aave,
|
||||||
tokens: [TOKENS.aDAI, TOKENS.aUSDC, TOKENS.aUSDT],
|
tokens: [TOKENS.aDAI, TOKENS.aUSDC, TOKENS.aUSDT],
|
||||||
metaToken: undefined,
|
metaToken: undefined,
|
||||||
},
|
},
|
||||||
@ -443,6 +536,52 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const NERVE_BSC_INFOS: { [name: string]: CurveInfo } = {
|
||||||
|
['0x1b3771a66ee31180906972580ade9b81afc5fcdc']: {
|
||||||
|
exchangeFunctionSelector: CurveFunctionSelectors.swap,
|
||||||
|
sellQuoteFunctionSelector: CurveFunctionSelectors.calculateSwap,
|
||||||
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
|
poolAddress: '0x1b3771a66ee31180906972580ade9b81afc5fcdc',
|
||||||
|
tokens: [
|
||||||
|
'0xe9e7cea3dedca5984780bafc599bd69add087d56', // BUSD
|
||||||
|
'0x55d398326f99059ff775485246999027b3197955', // BUSD-T
|
||||||
|
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC
|
||||||
|
],
|
||||||
|
metaToken: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BELT_BSC_INFOS: { [name: string]: CurveInfo } = {
|
||||||
|
['0xf16d312d119c13dd27fd0dc814b0bcdcaaa62dfd']: {
|
||||||
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange_underlying,
|
||||||
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy_underlying,
|
||||||
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
|
poolAddress: '0xf16d312d119c13dd27fd0dc814b0bcdcaaa62dfd',
|
||||||
|
tokens: [
|
||||||
|
'0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3', // bDAI
|
||||||
|
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC
|
||||||
|
'0x55d398326f99059ff775485246999027b3197955', // BUSD-T
|
||||||
|
'0xe9e7cea3dedca5984780bafc599bd69add087d56', // BUSD
|
||||||
|
],
|
||||||
|
metaToken: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ELLIPSIS_BSC_INFOS: { [name: string]: CurveInfo } = {
|
||||||
|
['0x160caed03795365f3a589f10c379ffa7d75d4e76']: {
|
||||||
|
exchangeFunctionSelector: CurveFunctionSelectors.exchange,
|
||||||
|
sellQuoteFunctionSelector: CurveFunctionSelectors.get_dy,
|
||||||
|
buyQuoteFunctionSelector: CurveFunctionSelectors.None,
|
||||||
|
poolAddress: '0x160caed03795365f3a589f10c379ffa7d75d4e76',
|
||||||
|
tokens: [
|
||||||
|
'0xe9e7cea3dedca5984780bafc599bd69add087d56', // BUSD
|
||||||
|
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC
|
||||||
|
'0x55d398326f99059ff775485246999027b3197955', // BUSD-T
|
||||||
|
],
|
||||||
|
metaToken: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kyber reserve prefixes
|
* Kyber reserve prefixes
|
||||||
* 0xff Fed price reserve
|
* 0xff Fed price reserve
|
||||||
@ -451,42 +590,138 @@ export const MAINNET_SNOWSWAP_INFOS: { [name: string]: CurveInfo } = {
|
|||||||
*/
|
*/
|
||||||
export const KYBER_BRIDGED_LIQUIDITY_PREFIX = '0xbb';
|
export const KYBER_BRIDGED_LIQUIDITY_PREFIX = '0xbb';
|
||||||
export const MAX_KYBER_RESERVES_QUERIED = 5;
|
export const MAX_KYBER_RESERVES_QUERIED = 5;
|
||||||
export const MAINNET_KYBER_NETWORK_PROXY = '0x9aab3f75489902f3a48495025729a0af77d4b11e';
|
export const KYBER_CONFIG_BY_CHAIN_ID = valueByChainId<KyberSamplerOpts>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: {
|
||||||
|
networkProxy: '0x9aab3f75489902f3a48495025729a0af77d4b11e',
|
||||||
|
hintHandler: '0xa1C0Fa73c39CFBcC11ec9Eb1Afc665aba9996E2C',
|
||||||
|
weth: TOKENS.WETH,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
networkProxy: NULL_ADDRESS,
|
||||||
|
hintHandler: NULL_ADDRESS,
|
||||||
|
weth: NULL_ADDRESS,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export const LIQUIDITY_PROVIDER_REGISTRY: LiquidityProviderRegistry = {};
|
export const LIQUIDITY_PROVIDER_REGISTRY: LiquidityProviderRegistry = {};
|
||||||
|
|
||||||
export const MAINNET_UNISWAP_V1_ROUTER = '0xc0a47dfe034b400b47bdad5fecda2621de6c4d95';
|
export const UNISWAPV1_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
export const MAINNET_UNISWAP_V2_ROUTER = '0xf164fc0ec4e93095b804a4795bbe1e041497b92a';
|
{
|
||||||
export const MAINNET_SUSHI_SWAP_ROUTER = '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f';
|
[ChainId.Mainnet]: '0xc0a47dfe034b400b47bdad5fecda2621de6c4d95',
|
||||||
export const MAINNET_CRYPTO_COM_ROUTER = '0xceb90e4c17d626be0facd78b79c9c87d7ca181b3';
|
},
|
||||||
export const MAINNET_LINKSWAP_ROUTER = '0xa7ece0911fe8c60bff9e99f8fafcdbe56e07aff1';
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
export const MAINNET_MSTABLE_ROUTER = '0xe2f2a5c287993345a840db3b0845fbc70f5935a5';
|
export const UNISWAPV2_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
export const MAINNET_OASIS_ROUTER = '0x794e6e91555438afc3ccf1c5076a74f42133d08d';
|
{
|
||||||
|
[ChainId.Mainnet]: '0xf164fc0ec4e93095b804a4795bbe1e041497b92a',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
export const MAINNET_MOONISWAP_REGISTRY = '0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303';
|
export const SUSHISWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
export const MAINNET_MOONISWAP_V2_REGISTRY = '0xc4a8b7e29e3c8ec560cd4945c1cf3461a85a148d';
|
{
|
||||||
export const MAINNET_MOONISWAP_V2_1_REGISTRY = '0xbaf9a5d4b0052359326a6cdab54babaa3a3a9643';
|
[ChainId.Mainnet]: '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f',
|
||||||
|
[ChainId.BSC]: '0x1b02da8cb0d097eb8d57a175b88c7d8b47997506',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
export const MAINNET_DODO_HELPER = '0x533da777aedce766ceae696bf90f8541a4ba80eb';
|
export const CRYPTO_COM_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
export const MAINNET_DODOV2_PRIVATE_POOL_FACTORY = '0x6b4fa0bc61eddc928e0df9c7f01e407bfcd3e5ef';
|
{
|
||||||
export const MAINNET_DODOV2_VENDING_MACHINE_FACTORY = '0x72d220ce168c4f361dd4dee5d826a01ad8598f6c';
|
[ChainId.Mainnet]: '0xceb90e4c17d626be0facd78b79c9c87d7ca181b3',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const LINKSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{ [ChainId.Mainnet]: '0xa7ece0911fe8c60bff9e99f8fafcdbe56e07aff1' },
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MSTABLE_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: '0xe2f2a5c287993345a840db3b0845fbc70f5935a5',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const OASIS_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: '0x5e3e0548935a83ad29fb2a9153d331dc6d49020f',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const MOONISWAP_REGISTRIES_BY_CHAIN_ID = valueByChainId(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: [
|
||||||
|
'0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303',
|
||||||
|
'0xc4a8b7e29e3c8ec560cd4945c1cf3461a85a148d',
|
||||||
|
'0xbaf9a5d4b0052359326a6cdab54babaa3a3a9643',
|
||||||
|
],
|
||||||
|
[ChainId.BSC]: ['0xd41b24bba51fac0e4827b6f94c0d6ddeb183cd64'],
|
||||||
|
},
|
||||||
|
[] as string[],
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DODO_CONFIG_BY_CHAIN_ID = valueByChainId(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: {
|
||||||
|
helper: '0x533da777aedce766ceae696bf90f8541a4ba80eb',
|
||||||
|
registry: '0x3A97247DF274a17C59A3bd12735ea3FcDFb49950',
|
||||||
|
},
|
||||||
|
[ChainId.BSC]: {
|
||||||
|
helper: '0x0f859706aee7fcf61d5a8939e8cb9dbb6c1eda33',
|
||||||
|
registry: '0xca459456a45e300aa7ef447dbb60f87cccb42828',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ helper: NULL_ADDRESS, registry: NULL_ADDRESS },
|
||||||
|
);
|
||||||
|
|
||||||
|
export const DODOV2_FACTORIES_BY_CHAIN_ID = valueByChainId<string[]>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: [
|
||||||
|
'0x6b4fa0bc61eddc928e0df9c7f01e407bfcd3e5ef', // Private Pool
|
||||||
|
'0x72d220ce168c4f361dd4dee5d826a01ad8598f6c', // Vending Machine
|
||||||
|
],
|
||||||
|
[ChainId.BSC]: [
|
||||||
|
'0xafe0a75dffb395eaabd0a7e1bbbd0b11f8609eef', // Private Pool
|
||||||
|
'0x790b4a80fb1094589a3c0efc8740aa9b0c1733fb', // Vending Machine
|
||||||
|
],
|
||||||
|
},
|
||||||
|
[] as string[],
|
||||||
|
);
|
||||||
export const MAX_DODOV2_POOLS_QUERIED = 3;
|
export const MAX_DODOV2_POOLS_QUERIED = 3;
|
||||||
|
|
||||||
export const CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID: { [id: string]: string } = {
|
export const CURVE_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
'1': '0x561b94454b65614ae3db0897b74303f4acf7cc75',
|
{
|
||||||
'3': '0xae241c6fc7f28f6dc0cb58b4112ba7f63fcaf5e2',
|
[ChainId.Mainnet]: '0x7a6F6a048fE2Dc1397ABa0bf7879d3eacF371C53',
|
||||||
'1337': NULL_ADDRESS,
|
[ChainId.Ropsten]: '0xAa213dcDFbF104e08cbAeC3d1628eD197553AfCc',
|
||||||
};
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
// TODO(dorothy-zbornak): Point these to real addresses after deploying.
|
export const MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
export const MOONISWAP_LIQUIDITY_PROVIDER_BY_CHAIN_ID: { [id: string]: string } = {
|
{
|
||||||
'1': '0xa2033d6ba88756ce6a87584d69dc87bda9a4f889',
|
[ChainId.Mainnet]: '0xa2033d6ba88756ce6a87584d69dc87bda9a4f889',
|
||||||
'3': '0x87e0393aee0fb8c10b8653c6507c182264fe5a34',
|
[ChainId.Ropsten]: '0x87e0393aee0fb8c10b8653c6507c182264fe5a34',
|
||||||
'1337': NULL_ADDRESS,
|
},
|
||||||
};
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
export const MAINNET_SHELL_POOLS = {
|
export const BANCOR_REGISTRY_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: '0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const SHELL_POOLS_BY_CHAIN_ID = valueByChainId(
|
||||||
|
{
|
||||||
|
[ChainId.Mainnet]: {
|
||||||
StableCoins: {
|
StableCoins: {
|
||||||
poolAddress: '0x8f26d7bab7a73309141a291525c965ecdea7bf42',
|
poolAddress: '0x8f26d7bab7a73309141a291525c965ecdea7bf42',
|
||||||
tokens: [TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD, TOKENS.DAI],
|
tokens: [TOKENS.USDC, TOKENS.USDT, TOKENS.sUSD, TOKENS.DAI],
|
||||||
@ -495,12 +730,41 @@ export const MAINNET_SHELL_POOLS = {
|
|||||||
poolAddress: '0xc2d019b901f8d4fdb2b9a65b5d226ad88c66ee8d',
|
poolAddress: '0xc2d019b901f8d4fdb2b9a65b5d226ad88c66ee8d',
|
||||||
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
tokens: [TOKENS.RenBTC, TOKENS.WBTC, TOKENS.sBTC],
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
StableCoins: {
|
||||||
|
poolAddress: NULL_ADDRESS,
|
||||||
|
tokens: [] as string[],
|
||||||
|
},
|
||||||
|
Bitcoin: {
|
||||||
|
poolAddress: NULL_ADDRESS,
|
||||||
|
tokens: [] as string[],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
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;
|
||||||
|
|
||||||
|
//
|
||||||
|
// BSC
|
||||||
|
//
|
||||||
|
export const PANCAKESWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.BSC]: '0x05ff2b0db69458a0750badebc4f9e13add608c7f',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const BAKERYSWAP_ROUTER_BY_CHAIN_ID = valueByChainId<string>(
|
||||||
|
{
|
||||||
|
[ChainId.BSC]: '0xcde540d7eafe93ac5fe6233bee57e1270d3e330f',
|
||||||
|
},
|
||||||
|
NULL_ADDRESS,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculated gross gas cost of the underlying exchange.
|
* Calculated gross gas cost of the underlying exchange.
|
||||||
* The cost of switching from one source to another, assuming
|
* The cost of switching from one source to another, assuming
|
||||||
@ -527,32 +791,32 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
[ERC20BridgeSource.Curve]: fillData => {
|
[ERC20BridgeSource.Curve]: fillData => {
|
||||||
const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase();
|
const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase();
|
||||||
switch (poolAddress) {
|
switch (poolAddress) {
|
||||||
case POOLS.curve_renBTC:
|
case CURVE_POOLS.curve_renBTC:
|
||||||
case POOLS.curve_sBTC:
|
case CURVE_POOLS.curve_sBTC:
|
||||||
case POOLS.curve_sUSD:
|
case CURVE_POOLS.curve_sUSD:
|
||||||
case POOLS.curve_HBTC:
|
case CURVE_POOLS.curve_HBTC:
|
||||||
case POOLS.curve_TRI:
|
case CURVE_POOLS.curve_TRI:
|
||||||
return 150e3;
|
return 150e3;
|
||||||
case POOLS.curve_USDN:
|
case CURVE_POOLS.curve_USDN:
|
||||||
case POOLS.curve_mUSD:
|
case CURVE_POOLS.curve_mUSD:
|
||||||
return 300e3;
|
return 300e3;
|
||||||
case POOLS.curve_GUSD:
|
case CURVE_POOLS.curve_GUSD:
|
||||||
case POOLS.curve_HUSD:
|
case CURVE_POOLS.curve_HUSD:
|
||||||
return 310e3;
|
return 310e3;
|
||||||
case POOLS.curve_tBTC:
|
case CURVE_POOLS.curve_tBTC:
|
||||||
return 370e3;
|
return 370e3;
|
||||||
case POOLS.curve_UST:
|
case CURVE_POOLS.curve_UST:
|
||||||
return 500e3;
|
return 500e3;
|
||||||
case POOLS.curve_dUSD:
|
case CURVE_POOLS.curve_dUSD:
|
||||||
case POOLS.curve_bBTC:
|
case CURVE_POOLS.curve_bBTC:
|
||||||
case POOLS.curve_oBTC:
|
case CURVE_POOLS.curve_oBTC:
|
||||||
case POOLS.curve_eurs:
|
case CURVE_POOLS.curve_eurs:
|
||||||
return 600e3;
|
return 600e3;
|
||||||
case POOLS.curve_compound:
|
case CURVE_POOLS.curve_compound:
|
||||||
return 750e3;
|
return 750e3;
|
||||||
case POOLS.curve_aave:
|
case CURVE_POOLS.curve_aave:
|
||||||
return 800e3;
|
return 800e3;
|
||||||
case POOLS.curve_PAX:
|
case CURVE_POOLS.curve_PAX:
|
||||||
return 850e3;
|
return 850e3;
|
||||||
// case POOLS.curve_seth:
|
// case POOLS.curve_seth:
|
||||||
default:
|
default:
|
||||||
@ -572,7 +836,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
[ERC20BridgeSource.SushiSwap]: (fillData?: FillData) => {
|
[ERC20BridgeSource.SushiSwap]: (fillData?: FillData) => {
|
||||||
// TODO: Different base cost if to/from ETH.
|
// TODO: Different base cost if to/from ETH.
|
||||||
let gas = 90e3;
|
let gas = 90e3;
|
||||||
const path = (fillData as SushiSwapFillData).tokenAddressPath;
|
const path = (fillData as UniswapV2FillData).tokenAddressPath;
|
||||||
if (path.length > 2) {
|
if (path.length > 2) {
|
||||||
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||||
}
|
}
|
||||||
@ -601,6 +865,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
[ERC20BridgeSource.MStable]: () => 700e3,
|
[ERC20BridgeSource.MStable]: () => 700e3,
|
||||||
[ERC20BridgeSource.Mooniswap]: () => 130e3,
|
[ERC20BridgeSource.Mooniswap]: () => 130e3,
|
||||||
[ERC20BridgeSource.Swerve]: () => 150e3,
|
[ERC20BridgeSource.Swerve]: () => 150e3,
|
||||||
|
[ERC20BridgeSource.Nerve]: () => 150e3,
|
||||||
[ERC20BridgeSource.Shell]: () => 170e3,
|
[ERC20BridgeSource.Shell]: () => 170e3,
|
||||||
[ERC20BridgeSource.MultiHop]: (fillData?: FillData) => {
|
[ERC20BridgeSource.MultiHop]: (fillData?: FillData) => {
|
||||||
const firstHop = (fillData as MultiHopFillData).firstHopSource;
|
const firstHop = (fillData as MultiHopFillData).firstHopSource;
|
||||||
@ -620,7 +885,7 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
},
|
},
|
||||||
[ERC20BridgeSource.DodoV2]: (_fillData?: FillData) => 100e3,
|
[ERC20BridgeSource.DodoV2]: (_fillData?: FillData) => 100e3,
|
||||||
[ERC20BridgeSource.SnowSwap]: fillData => {
|
[ERC20BridgeSource.SnowSwap]: fillData => {
|
||||||
switch ((fillData as SnowSwapFillData).pool.poolAddress.toLowerCase()) {
|
switch ((fillData as CurveFillData).pool.poolAddress.toLowerCase()) {
|
||||||
case '0xbf7ccd6c446acfcc5df023043f2167b62e81899b':
|
case '0xbf7ccd6c446acfcc5df023043f2167b62e81899b':
|
||||||
return 1000e3;
|
return 1000e3;
|
||||||
case '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b':
|
case '0x4571753311e37ddb44faa8fb78a6df9a6e3c6c0b':
|
||||||
@ -637,6 +902,29 @@ export const DEFAULT_GAS_SCHEDULE: Required<FeeSchedule> = {
|
|||||||
}
|
}
|
||||||
return gas;
|
return gas;
|
||||||
},
|
},
|
||||||
|
//
|
||||||
|
// BSC
|
||||||
|
//
|
||||||
|
[ERC20BridgeSource.PancakeSwap]: (fillData?: FillData) => {
|
||||||
|
// TODO: Different base cost if to/from ETH.
|
||||||
|
let gas = 90e3;
|
||||||
|
const path = (fillData as UniswapV2FillData).tokenAddressPath;
|
||||||
|
if (path.length > 2) {
|
||||||
|
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||||
|
}
|
||||||
|
return gas;
|
||||||
|
},
|
||||||
|
[ERC20BridgeSource.BakerySwap]: (fillData?: FillData) => {
|
||||||
|
// TODO: Different base cost if to/from ETH.
|
||||||
|
let gas = 90e3;
|
||||||
|
const path = (fillData as UniswapV2FillData).tokenAddressPath;
|
||||||
|
if (path.length > 2) {
|
||||||
|
gas += (path.length - 2) * 60e3; // +60k for each hop.
|
||||||
|
}
|
||||||
|
return gas;
|
||||||
|
},
|
||||||
|
[ERC20BridgeSource.Belt]: () => 4500e3,
|
||||||
|
[ERC20BridgeSource.Ellipsis]: () => 150e3,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = { ...DEFAULT_GAS_SCHEDULE };
|
export const DEFAULT_FEE_SCHEDULE: Required<FeeSchedule> = { ...DEFAULT_GAS_SCHEDULE };
|
||||||
|
@ -19,11 +19,12 @@ import {
|
|||||||
import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
|
import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
|
||||||
import { getComparisonPrices } from './comparison_price';
|
import { getComparisonPrices } from './comparison_price';
|
||||||
import {
|
import {
|
||||||
BUY_SOURCE_FILTER,
|
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
DEFAULT_GET_MARKET_ORDERS_OPTS,
|
||||||
FEE_QUOTE_SOURCES,
|
FEE_QUOTE_SOURCES_BY_CHAIN_ID,
|
||||||
ONE_ETHER,
|
NATIVE_FEE_TOKEN_AMOUNT_BY_CHAIN_ID,
|
||||||
SELL_SOURCE_FILTER,
|
NATIVE_FEE_TOKEN_BY_CHAIN_ID,
|
||||||
|
SELL_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
SOURCE_FLAGS,
|
SOURCE_FLAGS,
|
||||||
ZERO_AMOUNT,
|
ZERO_AMOUNT,
|
||||||
} from './constants';
|
} from './constants';
|
||||||
@ -50,10 +51,11 @@ import {
|
|||||||
// tslint:disable:boolean-naming
|
// tslint:disable:boolean-naming
|
||||||
|
|
||||||
export class MarketOperationUtils {
|
export class MarketOperationUtils {
|
||||||
private readonly _wethAddress: string;
|
|
||||||
private readonly _sellSources: SourceFilters;
|
private readonly _sellSources: SourceFilters;
|
||||||
private readonly _buySources: SourceFilters;
|
private readonly _buySources: SourceFilters;
|
||||||
private readonly _feeSources = new SourceFilters(FEE_QUOTE_SOURCES);
|
private readonly _feeSources: SourceFilters;
|
||||||
|
private readonly _nativeFeeToken: string;
|
||||||
|
private readonly _nativeFeeTokenAmount: BigNumber;
|
||||||
|
|
||||||
private static _computeQuoteReport(
|
private static _computeQuoteReport(
|
||||||
quoteRequestor: QuoteRequestor | undefined,
|
quoteRequestor: QuoteRequestor | undefined,
|
||||||
@ -71,9 +73,11 @@ export class MarketOperationUtils {
|
|||||||
private readonly contractAddresses: AssetSwapperContractAddresses,
|
private readonly contractAddresses: AssetSwapperContractAddresses,
|
||||||
private readonly _orderDomain: OrderDomain,
|
private readonly _orderDomain: OrderDomain,
|
||||||
) {
|
) {
|
||||||
this._wethAddress = contractAddresses.etherToken.toLowerCase();
|
this._buySources = BUY_SOURCE_FILTER_BY_CHAIN_ID[_sampler.chainId];
|
||||||
this._buySources = BUY_SOURCE_FILTER;
|
this._sellSources = SELL_SOURCE_FILTER_BY_CHAIN_ID[_sampler.chainId];
|
||||||
this._sellSources = SELL_SOURCE_FILTER;
|
this._feeSources = new SourceFilters(FEE_QUOTE_SOURCES_BY_CHAIN_ID[_sampler.chainId]);
|
||||||
|
this._nativeFeeToken = NATIVE_FEE_TOKEN_BY_CHAIN_ID[_sampler.chainId];
|
||||||
|
this._nativeFeeTokenAmount = NATIVE_FEE_TOKEN_AMOUNT_BY_CHAIN_ID[_sampler.chainId];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,9 +132,19 @@ export class MarketOperationUtils {
|
|||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
this._sampler.getLimitOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
||||||
// Get ETH -> maker token price.
|
// Get ETH -> maker token price.
|
||||||
this._sampler.getMedianSellRate(feeSourceFilters.sources, makerToken, this._wethAddress, ONE_ETHER),
|
this._sampler.getMedianSellRate(
|
||||||
|
feeSourceFilters.sources,
|
||||||
|
makerToken,
|
||||||
|
this._nativeFeeToken,
|
||||||
|
this._nativeFeeTokenAmount,
|
||||||
|
),
|
||||||
// Get ETH -> taker token price.
|
// Get ETH -> taker token price.
|
||||||
this._sampler.getMedianSellRate(feeSourceFilters.sources, takerToken, this._wethAddress, ONE_ETHER),
|
this._sampler.getMedianSellRate(
|
||||||
|
feeSourceFilters.sources,
|
||||||
|
takerToken,
|
||||||
|
this._nativeFeeToken,
|
||||||
|
this._nativeFeeTokenAmount,
|
||||||
|
),
|
||||||
// Get sell quotes for taker -> maker.
|
// Get sell quotes for taker -> maker.
|
||||||
this._sampler.getSellQuotes(
|
this._sampler.getSellQuotes(
|
||||||
quoteSourceFilters.exclude(offChainSources).sources,
|
quoteSourceFilters.exclude(offChainSources).sources,
|
||||||
@ -254,9 +268,19 @@ export class MarketOperationUtils {
|
|||||||
// Get native order fillable amounts.
|
// Get native order fillable amounts.
|
||||||
this._sampler.getLimitOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
this._sampler.getLimitOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.exchangeProxy),
|
||||||
// Get ETH -> makerToken token price.
|
// Get ETH -> makerToken token price.
|
||||||
this._sampler.getMedianSellRate(feeSourceFilters.sources, makerToken, this._wethAddress, ONE_ETHER),
|
this._sampler.getMedianSellRate(
|
||||||
|
feeSourceFilters.sources,
|
||||||
|
makerToken,
|
||||||
|
this._nativeFeeToken,
|
||||||
|
this._nativeFeeTokenAmount,
|
||||||
|
),
|
||||||
// Get ETH -> taker token price.
|
// Get ETH -> taker token price.
|
||||||
this._sampler.getMedianSellRate(feeSourceFilters.sources, takerToken, this._wethAddress, ONE_ETHER),
|
this._sampler.getMedianSellRate(
|
||||||
|
feeSourceFilters.sources,
|
||||||
|
takerToken,
|
||||||
|
this._nativeFeeToken,
|
||||||
|
this._nativeFeeTokenAmount,
|
||||||
|
),
|
||||||
// Get buy quotes for taker -> maker.
|
// Get buy quotes for taker -> maker.
|
||||||
this._sampler.getBuyQuotes(
|
this._sampler.getBuyQuotes(
|
||||||
quoteSourceFilters.exclude(offChainSources).sources,
|
quoteSourceFilters.exclude(offChainSources).sources,
|
||||||
@ -362,8 +386,8 @@ export class MarketOperationUtils {
|
|||||||
this._sampler.getMedianSellRate(
|
this._sampler.getMedianSellRate(
|
||||||
feeSourceFilters.sources,
|
feeSourceFilters.sources,
|
||||||
orders[0].order.takerToken,
|
orders[0].order.takerToken,
|
||||||
this._wethAddress,
|
this._nativeFeeToken,
|
||||||
ONE_ETHER,
|
this._nativeFeeTokenAmount,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...batchNativeOrders.map((orders, i) =>
|
...batchNativeOrders.map((orders, i) =>
|
||||||
|
@ -1,17 +1,9 @@
|
|||||||
import { BridgeSource, FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
import { BridgeProtocol, encodeBridgeSourceId, FillQuoteTransformerOrderType } from '@0x/protocol-utils';
|
||||||
import { AbiEncoder, BigNumber } from '@0x/utils';
|
import { AbiEncoder, BigNumber } from '@0x/utils';
|
||||||
|
|
||||||
import { AssetSwapperContractAddresses, MarketOperation } from '../../types';
|
import { AssetSwapperContractAddresses, MarketOperation } from '../../types';
|
||||||
|
|
||||||
import {
|
import { MAX_UINT256, ZERO_AMOUNT } from './constants';
|
||||||
MAINNET_DODO_HELPER,
|
|
||||||
MAINNET_KYBER_NETWORK_PROXY,
|
|
||||||
MAINNET_MSTABLE_ROUTER,
|
|
||||||
MAINNET_OASIS_ROUTER,
|
|
||||||
MAINNET_UNISWAP_V1_ROUTER,
|
|
||||||
MAX_UINT256,
|
|
||||||
ZERO_AMOUNT,
|
|
||||||
} from './constants';
|
|
||||||
import {
|
import {
|
||||||
AggregationError,
|
AggregationError,
|
||||||
BalancerFillData,
|
BalancerFillData,
|
||||||
@ -21,6 +13,7 @@ import {
|
|||||||
DexSample,
|
DexSample,
|
||||||
DODOFillData,
|
DODOFillData,
|
||||||
ERC20BridgeSource,
|
ERC20BridgeSource,
|
||||||
|
GenericRouterFillData,
|
||||||
KyberFillData,
|
KyberFillData,
|
||||||
LiquidityProviderFillData,
|
LiquidityProviderFillData,
|
||||||
MooniswapFillData,
|
MooniswapFillData,
|
||||||
@ -33,9 +26,6 @@ import {
|
|||||||
OptimizedMarketOrderBase,
|
OptimizedMarketOrderBase,
|
||||||
OrderDomain,
|
OrderDomain,
|
||||||
ShellFillData,
|
ShellFillData,
|
||||||
SnowSwapFillData,
|
|
||||||
SushiSwapFillData,
|
|
||||||
SwerveFillData,
|
|
||||||
UniswapV2FillData,
|
UniswapV2FillData,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
@ -80,48 +70,59 @@ export function createOrdersFromTwoHopSample(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getERC20BridgeSourceToBridgeSource(source: ERC20BridgeSource): BridgeSource {
|
export function getErc20BridgeSourceToBridgeSource(source: ERC20BridgeSource): string {
|
||||||
switch (source) {
|
switch (source) {
|
||||||
case ERC20BridgeSource.Balancer:
|
case ERC20BridgeSource.Balancer:
|
||||||
return BridgeSource.Balancer;
|
return encodeBridgeSourceId(BridgeProtocol.Balancer, 'Balancer');
|
||||||
case ERC20BridgeSource.Bancor:
|
case ERC20BridgeSource.Bancor:
|
||||||
return BridgeSource.Bancor;
|
return encodeBridgeSourceId(BridgeProtocol.Bancor, 'Bancor');
|
||||||
// case ERC20BridgeSource.CoFiX:
|
// case ERC20BridgeSource.CoFiX:
|
||||||
// return BridgeSource.CoFiX;
|
// return encodeBridgeSourceId(BridgeProtocol.CoFiX, 'CoFiX');
|
||||||
case ERC20BridgeSource.Curve:
|
case ERC20BridgeSource.Curve:
|
||||||
return BridgeSource.Curve;
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Curve');
|
||||||
case ERC20BridgeSource.Cream:
|
case ERC20BridgeSource.Cream:
|
||||||
return BridgeSource.Cream;
|
return encodeBridgeSourceId(BridgeProtocol.Balancer, 'Cream');
|
||||||
case ERC20BridgeSource.CryptoCom:
|
case ERC20BridgeSource.CryptoCom:
|
||||||
return BridgeSource.CryptoCom;
|
return encodeBridgeSourceId(BridgeProtocol.CryptoCom, 'CryptoCom');
|
||||||
case ERC20BridgeSource.Dodo:
|
case ERC20BridgeSource.Dodo:
|
||||||
return BridgeSource.Dodo;
|
return encodeBridgeSourceId(BridgeProtocol.Dodo, 'Dodo');
|
||||||
case ERC20BridgeSource.Kyber:
|
case ERC20BridgeSource.Kyber:
|
||||||
return BridgeSource.Kyber;
|
return encodeBridgeSourceId(BridgeProtocol.Kyber, 'Kyber');
|
||||||
case ERC20BridgeSource.LiquidityProvider:
|
case ERC20BridgeSource.LiquidityProvider:
|
||||||
return BridgeSource.LiquidityProvider;
|
// "LiquidityProvider" is too long to encode (17 characters).
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.Unknown, 'LP');
|
||||||
case ERC20BridgeSource.Mooniswap:
|
case ERC20BridgeSource.Mooniswap:
|
||||||
return BridgeSource.Mooniswap;
|
return encodeBridgeSourceId(BridgeProtocol.Mooniswap, 'Mooniswap');
|
||||||
case ERC20BridgeSource.MStable:
|
case ERC20BridgeSource.MStable:
|
||||||
return BridgeSource.MStable;
|
return encodeBridgeSourceId(BridgeProtocol.MStable, 'MStable');
|
||||||
case ERC20BridgeSource.Eth2Dai:
|
case ERC20BridgeSource.Eth2Dai:
|
||||||
return BridgeSource.Oasis;
|
return encodeBridgeSourceId(BridgeProtocol.Oasis, 'Eth2Dai');
|
||||||
case ERC20BridgeSource.Shell:
|
case ERC20BridgeSource.Shell:
|
||||||
return BridgeSource.Shell;
|
return encodeBridgeSourceId(BridgeProtocol.Shell, 'Shell');
|
||||||
case ERC20BridgeSource.SnowSwap:
|
case ERC20BridgeSource.SnowSwap:
|
||||||
return BridgeSource.Snowswap;
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'SnowSwap');
|
||||||
case ERC20BridgeSource.SushiSwap:
|
case ERC20BridgeSource.SushiSwap:
|
||||||
return BridgeSource.Sushiswap;
|
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'SushiSwap');
|
||||||
case ERC20BridgeSource.Swerve:
|
case ERC20BridgeSource.Swerve:
|
||||||
return BridgeSource.Swerve;
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Swerve');
|
||||||
case ERC20BridgeSource.Uniswap:
|
case ERC20BridgeSource.Uniswap:
|
||||||
return BridgeSource.Uniswap;
|
return encodeBridgeSourceId(BridgeProtocol.Uniswap, 'Uniswap');
|
||||||
case ERC20BridgeSource.UniswapV2:
|
case ERC20BridgeSource.UniswapV2:
|
||||||
return BridgeSource.UniswapV2;
|
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'UniswapV2');
|
||||||
case ERC20BridgeSource.DodoV2:
|
case ERC20BridgeSource.DodoV2:
|
||||||
return BridgeSource.DodoV2;
|
return encodeBridgeSourceId(BridgeProtocol.DodoV2, 'DodoV2');
|
||||||
case ERC20BridgeSource.Linkswap:
|
case ERC20BridgeSource.Linkswap:
|
||||||
return BridgeSource.Linkswap;
|
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'Linkswap');
|
||||||
|
case ERC20BridgeSource.PancakeSwap:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'PancakeSwap');
|
||||||
|
case ERC20BridgeSource.BakerySwap:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.UniswapV2, 'BakerySwap');
|
||||||
|
case ERC20BridgeSource.Nerve:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.Nerve, 'Nerve');
|
||||||
|
case ERC20BridgeSource.Belt:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Belt');
|
||||||
|
case ERC20BridgeSource.Ellipsis:
|
||||||
|
return encodeBridgeSourceId(BridgeProtocol.Curve, 'Ellipsis');
|
||||||
default:
|
default:
|
||||||
throw new Error(AggregationError.NoBridgeForSource);
|
throw new Error(AggregationError.NoBridgeForSource);
|
||||||
}
|
}
|
||||||
@ -146,9 +147,10 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
|
|||||||
case ERC20BridgeSource.Curve:
|
case ERC20BridgeSource.Curve:
|
||||||
case ERC20BridgeSource.Swerve:
|
case ERC20BridgeSource.Swerve:
|
||||||
case ERC20BridgeSource.SnowSwap:
|
case ERC20BridgeSource.SnowSwap:
|
||||||
const curveFillData = (order as OptimizedMarketBridgeOrder<
|
case ERC20BridgeSource.Nerve:
|
||||||
CurveFillData | SwerveFillData | SnowSwapFillData
|
case ERC20BridgeSource.Belt:
|
||||||
>).fillData;
|
case ERC20BridgeSource.Ellipsis:
|
||||||
|
const curveFillData = (order as OptimizedMarketBridgeOrder<CurveFillData>).fillData;
|
||||||
bridgeData = encoder.encode([
|
bridgeData = encoder.encode([
|
||||||
curveFillData.pool.poolAddress,
|
curveFillData.pool.poolAddress,
|
||||||
curveFillData.pool.exchangeFunctionSelector,
|
curveFillData.pool.exchangeFunctionSelector,
|
||||||
@ -169,13 +171,14 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
|
|||||||
case ERC20BridgeSource.SushiSwap:
|
case ERC20BridgeSource.SushiSwap:
|
||||||
case ERC20BridgeSource.CryptoCom:
|
case ERC20BridgeSource.CryptoCom:
|
||||||
case ERC20BridgeSource.Linkswap:
|
case ERC20BridgeSource.Linkswap:
|
||||||
const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData | SushiSwapFillData>)
|
case ERC20BridgeSource.PancakeSwap:
|
||||||
.fillData;
|
case ERC20BridgeSource.BakerySwap:
|
||||||
|
const uniswapV2FillData = (order as OptimizedMarketBridgeOrder<UniswapV2FillData>).fillData;
|
||||||
bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
|
bridgeData = encoder.encode([uniswapV2FillData.router, uniswapV2FillData.tokenAddressPath]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.Kyber:
|
case ERC20BridgeSource.Kyber:
|
||||||
const kyberFillData = (order as OptimizedMarketBridgeOrder<KyberFillData>).fillData;
|
const kyberFillData = (order as OptimizedMarketBridgeOrder<KyberFillData>).fillData;
|
||||||
bridgeData = encoder.encode([MAINNET_KYBER_NETWORK_PROXY, kyberFillData.hint]);
|
bridgeData = encoder.encode([kyberFillData.networkProxy, kyberFillData.hint]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.Mooniswap:
|
case ERC20BridgeSource.Mooniswap:
|
||||||
const mooniswapFillData = (order as OptimizedMarketBridgeOrder<MooniswapFillData>).fillData;
|
const mooniswapFillData = (order as OptimizedMarketBridgeOrder<MooniswapFillData>).fillData;
|
||||||
@ -183,7 +186,11 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
|
|||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.Dodo:
|
case ERC20BridgeSource.Dodo:
|
||||||
const dodoFillData = (order as OptimizedMarketBridgeOrder<DODOFillData>).fillData;
|
const dodoFillData = (order as OptimizedMarketBridgeOrder<DODOFillData>).fillData;
|
||||||
bridgeData = encoder.encode([MAINNET_DODO_HELPER, dodoFillData.poolAddress, dodoFillData.isSellBase]);
|
bridgeData = encoder.encode([
|
||||||
|
dodoFillData.helperAddress,
|
||||||
|
dodoFillData.poolAddress,
|
||||||
|
dodoFillData.isSellBase,
|
||||||
|
]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.DodoV2:
|
case ERC20BridgeSource.DodoV2:
|
||||||
const dodoV2FillData = (order as OptimizedMarketBridgeOrder<DODOFillData>).fillData;
|
const dodoV2FillData = (order as OptimizedMarketBridgeOrder<DODOFillData>).fillData;
|
||||||
@ -198,13 +205,16 @@ export function createBridgeDataForBridgeOrder(order: OptimizedMarketBridgeOrder
|
|||||||
bridgeData = encoder.encode([lpFillData.poolAddress, tokenAddressEncoder.encode([order.takerToken])]);
|
bridgeData = encoder.encode([lpFillData.poolAddress, tokenAddressEncoder.encode([order.takerToken])]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.Uniswap:
|
case ERC20BridgeSource.Uniswap:
|
||||||
bridgeData = encoder.encode([MAINNET_UNISWAP_V1_ROUTER]);
|
const uniFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
|
||||||
|
bridgeData = encoder.encode([uniFillData.router]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.Eth2Dai:
|
case ERC20BridgeSource.Eth2Dai:
|
||||||
bridgeData = encoder.encode([MAINNET_OASIS_ROUTER]);
|
const oasisFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
|
||||||
|
bridgeData = encoder.encode([oasisFillData.router]);
|
||||||
break;
|
break;
|
||||||
case ERC20BridgeSource.MStable:
|
case ERC20BridgeSource.MStable:
|
||||||
bridgeData = encoder.encode([MAINNET_MSTABLE_ROUTER]);
|
const mStableFillData = (order as OptimizedMarketBridgeOrder<GenericRouterFillData>).fillData;
|
||||||
|
bridgeData = encoder.encode([mStableFillData.router]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(AggregationError.NoBridgeForSource);
|
throw new Error(AggregationError.NoBridgeForSource);
|
||||||
@ -275,6 +285,9 @@ export const BRIDGE_ENCODERS: {
|
|||||||
[ERC20BridgeSource.Curve]: curveEncoder,
|
[ERC20BridgeSource.Curve]: curveEncoder,
|
||||||
[ERC20BridgeSource.Swerve]: curveEncoder,
|
[ERC20BridgeSource.Swerve]: curveEncoder,
|
||||||
[ERC20BridgeSource.SnowSwap]: curveEncoder,
|
[ERC20BridgeSource.SnowSwap]: curveEncoder,
|
||||||
|
[ERC20BridgeSource.Nerve]: curveEncoder,
|
||||||
|
[ERC20BridgeSource.Belt]: curveEncoder,
|
||||||
|
[ERC20BridgeSource.Ellipsis]: curveEncoder,
|
||||||
// UniswapV2 like, (router, address[])
|
// UniswapV2 like, (router, address[])
|
||||||
[ERC20BridgeSource.Bancor]: routerAddressPathEncoder,
|
[ERC20BridgeSource.Bancor]: routerAddressPathEncoder,
|
||||||
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
|
[ERC20BridgeSource.UniswapV2]: routerAddressPathEncoder,
|
||||||
@ -289,6 +302,9 @@ export const BRIDGE_ENCODERS: {
|
|||||||
[ERC20BridgeSource.Balancer]: poolEncoder,
|
[ERC20BridgeSource.Balancer]: poolEncoder,
|
||||||
[ERC20BridgeSource.Cream]: poolEncoder,
|
[ERC20BridgeSource.Cream]: poolEncoder,
|
||||||
[ERC20BridgeSource.Uniswap]: poolEncoder,
|
[ERC20BridgeSource.Uniswap]: poolEncoder,
|
||||||
|
// BSC
|
||||||
|
[ERC20BridgeSource.PancakeSwap]: routerAddressPathEncoder,
|
||||||
|
[ERC20BridgeSource.BakerySwap]: routerAddressPathEncoder,
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {
|
function getFillTokenAmounts(fill: CollapsedFill, side: MarketOperation): [BigNumber, BigNumber] {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ChainId } from '@0x/contract-addresses';
|
||||||
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
import { BigNumber, NULL_BYTES } from '@0x/utils';
|
||||||
|
|
||||||
import { SamplerOverrides } from '../../types';
|
import { SamplerOverrides } from '../../types';
|
||||||
@ -33,6 +34,7 @@ type BatchedOperationResult<T> = T extends BatchedOperation<infer TResult> ? TRe
|
|||||||
*/
|
*/
|
||||||
export class DexOrderSampler extends SamplerOperations {
|
export class DexOrderSampler extends SamplerOperations {
|
||||||
constructor(
|
constructor(
|
||||||
|
public readonly chainId: ChainId,
|
||||||
_samplerContract: ERC20BridgeSamplerContract,
|
_samplerContract: ERC20BridgeSamplerContract,
|
||||||
private readonly _samplerOverrides?: SamplerOverrides,
|
private readonly _samplerOverrides?: SamplerOverrides,
|
||||||
balancerPoolsCache?: BalancerPoolsCache,
|
balancerPoolsCache?: BalancerPoolsCache,
|
||||||
@ -42,6 +44,7 @@ export class DexOrderSampler extends SamplerOperations {
|
|||||||
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
|
bancorServiceFn: () => Promise<BancorService | undefined> = async () => undefined,
|
||||||
) {
|
) {
|
||||||
super(
|
super(
|
||||||
|
chainId,
|
||||||
_samplerContract,
|
_samplerContract,
|
||||||
balancerPoolsCache,
|
balancerPoolsCache,
|
||||||
creamPoolsCache,
|
creamPoolsCache,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
|||||||
import { MAINNET_SHELL_POOLS } from './constants';
|
|
||||||
|
|
||||||
// tslint:disable completed-docs
|
|
||||||
export function getShellsForPair(takerToken: string, makerToken: string): string[] {
|
|
||||||
return Object.values(MAINNET_SHELL_POOLS)
|
|
||||||
.filter(c => [makerToken, takerToken].every(t => c.tokens.includes(t)))
|
|
||||||
.map(i => i.poolAddress);
|
|
||||||
}
|
|
@ -58,6 +58,12 @@ export enum ERC20BridgeSource {
|
|||||||
DodoV2 = 'DODO_V2',
|
DodoV2 = 'DODO_V2',
|
||||||
CryptoCom = 'CryptoCom',
|
CryptoCom = 'CryptoCom',
|
||||||
Linkswap = 'Linkswap',
|
Linkswap = 'Linkswap',
|
||||||
|
// Other
|
||||||
|
PancakeSwap = 'PancakeSwap',
|
||||||
|
BakerySwap = 'BakerySwap',
|
||||||
|
Nerve = 'Nerve',
|
||||||
|
Belt = 'Belt',
|
||||||
|
Ellipsis = 'Ellipsis',
|
||||||
}
|
}
|
||||||
|
|
||||||
// tslint:disable: enum-naming
|
// tslint:disable: enum-naming
|
||||||
@ -72,6 +78,9 @@ export enum CurveFunctionSelectors {
|
|||||||
get_dx_underlying = '0x0e71d1b9',
|
get_dx_underlying = '0x0e71d1b9',
|
||||||
get_dy = '0x5e0d443f',
|
get_dy = '0x5e0d443f',
|
||||||
get_dx = '0x67df02ca',
|
get_dx = '0x67df02ca',
|
||||||
|
// Nerve BSC
|
||||||
|
swap = '0x91695586',
|
||||||
|
calculateSwap = '0xa95b089f',
|
||||||
}
|
}
|
||||||
// tslint:enable: enum-naming
|
// tslint:enable: enum-naming
|
||||||
|
|
||||||
@ -87,9 +96,6 @@ export interface CurveInfo {
|
|||||||
metaToken: string | undefined;
|
metaToken: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SwerveInfo extends CurveInfo {}
|
|
||||||
export interface SnowSwapInfo extends CurveInfo {}
|
|
||||||
|
|
||||||
// Internal `fillData` field for `Fill` objects.
|
// Internal `fillData` field for `Fill` objects.
|
||||||
export interface FillData {}
|
export interface FillData {}
|
||||||
|
|
||||||
@ -111,18 +117,6 @@ export interface CurveFillData extends FillData {
|
|||||||
pool: CurveInfo;
|
pool: CurveInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SwerveFillData extends FillData {
|
|
||||||
fromTokenIdx: number;
|
|
||||||
toTokenIdx: number;
|
|
||||||
pool: SwerveInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SnowSwapFillData extends FillData {
|
|
||||||
fromTokenIdx: number;
|
|
||||||
toTokenIdx: number;
|
|
||||||
pool: SnowSwapInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BalancerFillData extends FillData {
|
export interface BalancerFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
@ -132,8 +126,6 @@ export interface UniswapV2FillData extends FillData {
|
|||||||
router: string;
|
router: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SushiSwapFillData extends UniswapV2FillData {}
|
|
||||||
|
|
||||||
export interface ShellFillData extends FillData {
|
export interface ShellFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
}
|
}
|
||||||
@ -151,6 +143,7 @@ export interface BancorFillData extends FillData {
|
|||||||
export interface KyberFillData extends FillData {
|
export interface KyberFillData extends FillData {
|
||||||
hint: string;
|
hint: string;
|
||||||
reserveId: string;
|
reserveId: string;
|
||||||
|
networkProxy: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MooniswapFillData extends FillData {
|
export interface MooniswapFillData extends FillData {
|
||||||
@ -160,7 +153,13 @@ export interface MooniswapFillData extends FillData {
|
|||||||
export interface DODOFillData extends FillData {
|
export interface DODOFillData extends FillData {
|
||||||
poolAddress: string;
|
poolAddress: string;
|
||||||
isSellBase: boolean;
|
isSellBase: boolean;
|
||||||
|
helperAddress: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface GenericRouterFillData extends FillData {
|
||||||
|
router: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MultiHopFillData extends FillData {
|
export interface MultiHopFillData extends FillData {
|
||||||
firstHopSource: SourceQuoteOperation;
|
firstHopSource: SourceQuoteOperation;
|
||||||
secondHopSource: SourceQuoteOperation;
|
secondHopSource: SourceQuoteOperation;
|
||||||
@ -440,3 +439,9 @@ export interface GenerateOptimizedOrdersOpts {
|
|||||||
export interface ComparisonPrice {
|
export interface ComparisonPrice {
|
||||||
wholeOrder: BigNumber | undefined;
|
wholeOrder: BigNumber | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface KyberSamplerOpts {
|
||||||
|
networkProxy: string;
|
||||||
|
hintHandler: string;
|
||||||
|
weth: string;
|
||||||
|
}
|
||||||
|
@ -10,7 +10,6 @@ import * as BalanceChecker from '../test/generated-artifacts/BalanceChecker.json
|
|||||||
import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json';
|
import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.json';
|
||||||
import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json';
|
import * as BancorSampler from '../test/generated-artifacts/BancorSampler.json';
|
||||||
import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json';
|
import * as CurveSampler from '../test/generated-artifacts/CurveSampler.json';
|
||||||
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
|
|
||||||
import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json';
|
import * as DODOSampler from '../test/generated-artifacts/DODOSampler.json';
|
||||||
import * as DODOV2Sampler from '../test/generated-artifacts/DODOV2Sampler.json';
|
import * as DODOV2Sampler from '../test/generated-artifacts/DODOV2Sampler.json';
|
||||||
import * as DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquidityProvider.json';
|
import * as DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquidityProvider.json';
|
||||||
@ -36,7 +35,6 @@ import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSamp
|
|||||||
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 ShellSampler from '../test/generated-artifacts/ShellSampler.json';
|
import * as ShellSampler from '../test/generated-artifacts/ShellSampler.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';
|
||||||
@ -51,7 +49,6 @@ export const artifacts = {
|
|||||||
CurveSampler: CurveSampler as ContractArtifact,
|
CurveSampler: CurveSampler as ContractArtifact,
|
||||||
DODOSampler: DODOSampler as ContractArtifact,
|
DODOSampler: DODOSampler as ContractArtifact,
|
||||||
DODOV2Sampler: DODOV2Sampler as ContractArtifact,
|
DODOV2Sampler: DODOV2Sampler as ContractArtifact,
|
||||||
DeploymentConstants: DeploymentConstants as ContractArtifact,
|
|
||||||
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
|
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
|
||||||
Eth2DaiSampler: Eth2DaiSampler as ContractArtifact,
|
Eth2DaiSampler: Eth2DaiSampler as ContractArtifact,
|
||||||
FakeTaker: FakeTaker as ContractArtifact,
|
FakeTaker: FakeTaker as ContractArtifact,
|
||||||
@ -63,7 +60,6 @@ export const artifacts = {
|
|||||||
NativeOrderSampler: NativeOrderSampler as ContractArtifact,
|
NativeOrderSampler: NativeOrderSampler as ContractArtifact,
|
||||||
SamplerUtils: SamplerUtils as ContractArtifact,
|
SamplerUtils: SamplerUtils as ContractArtifact,
|
||||||
ShellSampler: ShellSampler as ContractArtifact,
|
ShellSampler: ShellSampler 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,
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
|
import { ChainId } from '@0x/contract-addresses';
|
||||||
import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils';
|
import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils';
|
||||||
import { RPCSubprovider } from '@0x/subproviders';
|
import { RPCSubprovider } from '@0x/subproviders';
|
||||||
import { BigNumber, providerUtils } from '@0x/utils';
|
import { BigNumber, NULL_BYTES, providerUtils } from '@0x/utils';
|
||||||
|
|
||||||
|
import { KYBER_CONFIG_BY_CHAIN_ID, TOKENS } from '../../src/utils/market_operation_utils/constants';
|
||||||
import { artifacts } from '../artifacts';
|
import { artifacts } from '../artifacts';
|
||||||
import { ERC20BridgeSamplerContract } from '../wrappers';
|
import { ERC20BridgeSamplerContract } from '../wrappers';
|
||||||
|
|
||||||
@ -78,28 +80,33 @@ blockchainTests.skip('Mainnet Sampler Tests', env => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('Kyber', () => {
|
describe('Kyber', () => {
|
||||||
const WETH = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2';
|
const WETH = TOKENS.WETH;
|
||||||
const DAI = '0x6b175474e89094c44da98b954eedeac495271d0f';
|
const DAI = TOKENS.DAI;
|
||||||
const USDC = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48';
|
const USDC = TOKENS.USDC;
|
||||||
const RESERVE_OFFSET = new BigNumber(0);
|
const RESERVE_OFFSET = new BigNumber(0);
|
||||||
|
const KYBER_OPTS = {
|
||||||
|
...KYBER_CONFIG_BY_CHAIN_ID[ChainId.Mainnet],
|
||||||
|
reserveOffset: RESERVE_OFFSET,
|
||||||
|
hint: NULL_BYTES,
|
||||||
|
};
|
||||||
describe('sampleSellsFromKyberNetwork()', () => {
|
describe('sampleSellsFromKyberNetwork()', () => {
|
||||||
it('samples sells from Kyber DAI->WETH', async () => {
|
it('samples sells from Kyber DAI->WETH', async () => {
|
||||||
const [, samples] = await testContract
|
const [, samples] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(RESERVE_OFFSET, DAI, WETH, [toBaseUnitAmount(1)])
|
.sampleSellsFromKyberNetwork(KYBER_OPTS, DAI, WETH, [toBaseUnitAmount(1)])
|
||||||
.callAsync({ overrides });
|
.callAsync({ overrides });
|
||||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
});
|
});
|
||||||
it('samples sells from Kyber WETH->DAI', async () => {
|
it('samples sells from Kyber WETH->DAI', async () => {
|
||||||
const [, samples] = await testContract
|
const [, samples] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(RESERVE_OFFSET, WETH, DAI, [toBaseUnitAmount(1)])
|
.sampleSellsFromKyberNetwork(KYBER_OPTS, WETH, DAI, [toBaseUnitAmount(1)])
|
||||||
.callAsync({ overrides });
|
.callAsync({ overrides });
|
||||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
});
|
});
|
||||||
it('samples sells from Kyber DAI->USDC', async () => {
|
it('samples sells from Kyber DAI->USDC', async () => {
|
||||||
const [, samples] = await testContract
|
const [, samples] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(RESERVE_OFFSET, DAI, USDC, [toBaseUnitAmount(1)])
|
.sampleSellsFromKyberNetwork(KYBER_OPTS, DAI, USDC, [toBaseUnitAmount(1)])
|
||||||
.callAsync({ overrides });
|
.callAsync({ overrides });
|
||||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
@ -111,7 +118,7 @@ blockchainTests.skip('Mainnet Sampler Tests', env => {
|
|||||||
// From ETH to DAI
|
// From ETH to DAI
|
||||||
// I want to buy 1 DAI
|
// I want to buy 1 DAI
|
||||||
const [, samples] = await testContract
|
const [, samples] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(RESERVE_OFFSET, WETH, DAI, [toBaseUnitAmount(1)])
|
.sampleBuysFromKyberNetwork(KYBER_OPTS, WETH, DAI, [toBaseUnitAmount(1)])
|
||||||
.callAsync({ overrides });
|
.callAsync({ overrides });
|
||||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
@ -121,7 +128,7 @@ blockchainTests.skip('Mainnet Sampler Tests', env => {
|
|||||||
// From USDC to DAI
|
// From USDC to DAI
|
||||||
// I want to buy 1 WETH
|
// I want to buy 1 WETH
|
||||||
const [, samples] = await testContract
|
const [, samples] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(RESERVE_OFFSET, DAI, WETH, [toBaseUnitAmount(1)])
|
.sampleBuysFromKyberNetwork(KYBER_OPTS, DAI, WETH, [toBaseUnitAmount(1)])
|
||||||
.callAsync({ overrides });
|
.callAsync({ overrides });
|
||||||
expect(samples.length).to.be.bignumber.greaterThan(0);
|
expect(samples.length).to.be.bignumber.greaterThan(0);
|
||||||
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
expect(samples[0]).to.be.bignumber.greaterThan(0);
|
||||||
|
@ -31,12 +31,15 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const ETH2DAI_SALT = '0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7';
|
const ETH2DAI_SALT = '0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7';
|
||||||
const UNISWAP_BASE_SALT = '0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab';
|
const UNISWAP_BASE_SALT = '0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab';
|
||||||
const UNISWAP_V2_SALT = '0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1';
|
const UNISWAP_V2_SALT = '0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1';
|
||||||
let UNISWAP_V2_ROUTER = '';
|
|
||||||
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
|
const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR';
|
||||||
const MAKER_TOKEN = randomAddress();
|
const MAKER_TOKEN = randomAddress();
|
||||||
const TAKER_TOKEN = randomAddress();
|
const TAKER_TOKEN = randomAddress();
|
||||||
const INTERMEDIATE_TOKEN = randomAddress();
|
const INTERMEDIATE_TOKEN = randomAddress();
|
||||||
const KYBER_RESERVE_OFFSET = new BigNumber(0);
|
const KYBER_RESERVE_OFFSET = new BigNumber(0);
|
||||||
|
let KYBER_ADDRESS = '';
|
||||||
|
let ETH2DAI_ADDRESS = '';
|
||||||
|
let UNISWAP_ADDRESS = '';
|
||||||
|
let UNISWAP_V2_ROUTER = '';
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
testContract = await TestERC20BridgeSamplerContract.deployFrom0xArtifactAsync(
|
testContract = await TestERC20BridgeSamplerContract.deployFrom0xArtifactAsync(
|
||||||
@ -46,6 +49,9 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
UNISWAP_V2_ROUTER = await testContract.uniswapV2Router().callAsync();
|
UNISWAP_V2_ROUTER = await testContract.uniswapV2Router().callAsync();
|
||||||
|
KYBER_ADDRESS = await testContract.kyber().callAsync();
|
||||||
|
ETH2DAI_ADDRESS = await testContract.eth2Dai().callAsync();
|
||||||
|
UNISWAP_ADDRESS = await testContract.uniswap().callAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
function getPackedHash(...args: string[]): string {
|
function getPackedHash(...args: string[]): string {
|
||||||
@ -331,20 +337,30 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
blockchainTests.resets('sampleSellsFromKyberNetwork()', () => {
|
blockchainTests.resets('sampleSellsFromKyberNetwork()', () => {
|
||||||
|
let kyberOpts = {
|
||||||
|
hintHandler: NULL_ADDRESS,
|
||||||
|
networkProxy: NULL_ADDRESS,
|
||||||
|
weth: WETH_ADDRESS,
|
||||||
|
reserveOffset: KYBER_RESERVE_OFFSET,
|
||||||
|
hint: NULL_BYTES,
|
||||||
|
};
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
||||||
|
kyberOpts = {
|
||||||
|
...kyberOpts,
|
||||||
|
hintHandler: KYBER_ADDRESS,
|
||||||
|
networkProxy: KYBER_ADDRESS,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract
|
const tx = testContract.sampleSellsFromKyberNetwork(kyberOpts, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, MAKER_TOKEN, MAKER_TOKEN, [])
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, [])
|
.sampleSellsFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
@ -354,7 +370,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -363,7 +379,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -372,7 +388,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -382,7 +398,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -391,7 +407,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -401,28 +417,38 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleSellsFromKyberNetwork(KYBER_RESERVE_OFFSET, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromKyberNetwork(kyberOpts, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
blockchainTests.resets('sampleBuysFromKyberNetwork()', () => {
|
blockchainTests.resets('sampleBuysFromKyberNetwork()', () => {
|
||||||
|
let kyberOpts = {
|
||||||
|
hintHandler: NULL_ADDRESS,
|
||||||
|
networkProxy: NULL_ADDRESS,
|
||||||
|
weth: WETH_ADDRESS,
|
||||||
|
reserveOffset: KYBER_RESERVE_OFFSET,
|
||||||
|
hint: NULL_BYTES,
|
||||||
|
};
|
||||||
const ACCEPTABLE_SLIPPAGE = 0.0005;
|
const ACCEPTABLE_SLIPPAGE = 0.0005;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
||||||
|
kyberOpts = {
|
||||||
|
...kyberOpts,
|
||||||
|
hintHandler: KYBER_ADDRESS,
|
||||||
|
networkProxy: KYBER_ADDRESS,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract
|
const tx = testContract.sampleBuysFromKyberNetwork(kyberOpts, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, MAKER_TOKEN, MAKER_TOKEN, [])
|
|
||||||
.callAsync();
|
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, [])
|
.sampleBuysFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
@ -431,7 +457,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
||||||
});
|
});
|
||||||
@ -441,7 +467,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -450,7 +476,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
||||||
});
|
});
|
||||||
@ -460,7 +486,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -469,7 +495,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Kyber'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Kyber'], sampleAmounts);
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
expectQuotesWithinRange(quotes, expectedQuotes, ACCEPTABLE_SLIPPAGE);
|
||||||
});
|
});
|
||||||
@ -479,7 +505,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const [, , quotes] = await testContract
|
const [, , quotes] = await testContract
|
||||||
.sampleBuysFromKyberNetwork(KYBER_RESERVE_OFFSET, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromKyberNetwork(kyberOpts, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -491,12 +517,14 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract.sampleSellsFromEth2Dai(MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const tx = testContract.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const quotes = await testContract.sampleSellsFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const quotes = await testContract
|
||||||
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -504,7 +532,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -514,7 +542,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -523,7 +551,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -533,7 +561,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -542,7 +570,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -552,7 +580,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromEth2Dai(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -564,12 +592,14 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract.sampleBuysFromEth2Dai(MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const tx = testContract.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const quotes = await testContract.sampleBuysFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const quotes = await testContract
|
||||||
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -577,7 +607,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -587,7 +617,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -596,7 +626,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -606,7 +636,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -615,7 +645,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Eth2Dai'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -625,24 +655,27 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromEth2Dai(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
blockchainTests.resets('sampleSellsFromUniswap()', () => {
|
blockchainTests.resets('sampleSellsFromUniswap()', () => {
|
||||||
|
const UNISWAP_ETH_ADDRESS = NULL_ADDRESS;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract.sampleSellsFromUniswap(MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const tx = testContract.sampleSellsFromUniswap(UNISWAP_ADDRESS, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const quotes = await testContract.sampleSellsFromUniswap(TAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const quotes = await testContract
|
||||||
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -650,7 +683,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -660,7 +693,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -669,7 +702,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, UNISWAP_ETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -679,7 +712,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, UNISWAP_ETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -688,7 +721,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicSellQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, UNISWAP_ETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -698,7 +731,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, UNISWAP_ETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -708,7 +741,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(TAKER_TOKEN);
|
||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(TAKER_TOKEN, nonExistantToken, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, nonExistantToken, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -718,24 +751,27 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(nonExistantToken);
|
const sampleAmounts = getSampleAmounts(nonExistantToken);
|
||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleSellsFromUniswap(nonExistantToken, MAKER_TOKEN, sampleAmounts)
|
.sampleSellsFromUniswap(UNISWAP_ADDRESS, nonExistantToken, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
blockchainTests.resets('sampleBuysFromUniswap()', () => {
|
blockchainTests.resets('sampleBuysFromUniswap()', () => {
|
||||||
|
const UNISWAP_ETH_ADDRESS = NULL_ADDRESS;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if tokens are the same', async () => {
|
it('throws if tokens are the same', async () => {
|
||||||
const tx = testContract.sampleBuysFromUniswap(MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const tx = testContract.sampleBuysFromUniswap(UNISWAP_ADDRESS, MAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
||||||
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
return expect(tx).to.revertWith(INVALID_TOKEN_PAIR_ERROR);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can return no quotes', async () => {
|
it('can return no quotes', async () => {
|
||||||
const quotes = await testContract.sampleBuysFromUniswap(TAKER_TOKEN, MAKER_TOKEN, []).callAsync();
|
const quotes = await testContract
|
||||||
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, [])
|
||||||
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq([]);
|
expect(quotes).to.deep.eq([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -743,7 +779,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, MAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -753,7 +789,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -762,7 +798,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(TAKER_TOKEN, WETH_ADDRESS, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, UNISWAP_ETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -772,7 +808,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(TAKER_TOKEN, WETH_ADDRESS, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, UNISWAP_ETH_ADDRESS, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -781,7 +817,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
const [expectedQuotes] = getDeterministicBuyQuotes(WETH_ADDRESS, TAKER_TOKEN, ['Uniswap'], sampleAmounts);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, UNISWAP_ETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -791,7 +827,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
await enableFailTriggerAsync();
|
await enableFailTriggerAsync();
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(WETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, UNISWAP_ETH_ADDRESS, TAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -801,7 +837,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(nonExistantToken);
|
const sampleAmounts = getSampleAmounts(nonExistantToken);
|
||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(TAKER_TOKEN, nonExistantToken, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, TAKER_TOKEN, nonExistantToken, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -811,7 +847,7 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
const sampleAmounts = getSampleAmounts(MAKER_TOKEN);
|
||||||
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT);
|
||||||
const quotes = await testContract
|
const quotes = await testContract
|
||||||
.sampleBuysFromUniswap(nonExistantToken, MAKER_TOKEN, sampleAmounts)
|
.sampleBuysFromUniswap(UNISWAP_ADDRESS, nonExistantToken, MAKER_TOKEN, sampleAmounts)
|
||||||
.callAsync();
|
.callAsync();
|
||||||
expect(quotes).to.deep.eq(expectedQuotes);
|
expect(quotes).to.deep.eq(expectedQuotes);
|
||||||
});
|
});
|
||||||
@ -1060,10 +1096,10 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
|
|
||||||
const eth2DaiFirstHop = testContract
|
const eth2DaiFirstHop = testContract
|
||||||
.sampleSellsFromEth2Dai(TAKER_TOKEN, INTERMEDIATE_TOKEN, [constants.ZERO_AMOUNT])
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, INTERMEDIATE_TOKEN, [constants.ZERO_AMOUNT])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
const eth2DaiSecondHop = testContract
|
const eth2DaiSecondHop = testContract
|
||||||
.sampleSellsFromEth2Dai(INTERMEDIATE_TOKEN, MAKER_TOKEN, [constants.ZERO_AMOUNT])
|
.sampleSellsFromEth2Dai(ETH2DAI_ADDRESS, INTERMEDIATE_TOKEN, MAKER_TOKEN, [constants.ZERO_AMOUNT])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
|
|
||||||
const firstHopQuotes = [
|
const firstHopQuotes = [
|
||||||
@ -1111,10 +1147,10 @@ blockchainTests('erc20-bridge-sampler', env => {
|
|||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
|
|
||||||
const eth2DaiFirstHop = testContract
|
const eth2DaiFirstHop = testContract
|
||||||
.sampleBuysFromEth2Dai(TAKER_TOKEN, INTERMEDIATE_TOKEN, [constants.ZERO_AMOUNT])
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, TAKER_TOKEN, INTERMEDIATE_TOKEN, [constants.ZERO_AMOUNT])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
const eth2DaiSecondHop = testContract
|
const eth2DaiSecondHop = testContract
|
||||||
.sampleBuysFromEth2Dai(INTERMEDIATE_TOKEN, MAKER_TOKEN, [constants.ZERO_AMOUNT])
|
.sampleBuysFromEth2Dai(ETH2DAI_ADDRESS, INTERMEDIATE_TOKEN, MAKER_TOKEN, [constants.ZERO_AMOUNT])
|
||||||
.getABIEncodedTransactionData();
|
.getABIEncodedTransactionData();
|
||||||
|
|
||||||
const secondHopQuotes = [
|
const secondHopQuotes = [
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
|
||||||
import {
|
import {
|
||||||
constants,
|
constants,
|
||||||
expect,
|
expect,
|
||||||
@ -26,6 +26,7 @@ const EMPTY_BYTES32 = '0x0000000000000000000000000000000000000000000000000000000
|
|||||||
describe('DexSampler tests', () => {
|
describe('DexSampler tests', () => {
|
||||||
const MAKER_TOKEN = randomAddress();
|
const MAKER_TOKEN = randomAddress();
|
||||||
const TAKER_TOKEN = randomAddress();
|
const TAKER_TOKEN = randomAddress();
|
||||||
|
const chainId = ChainId.Mainnet;
|
||||||
|
|
||||||
const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken;
|
const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken;
|
||||||
const exchangeProxyAddress = getContractAddressesForChainOrThrow(CHAIN_ID).exchangeProxy;
|
const exchangeProxyAddress = getContractAddressesForChainOrThrow(CHAIN_ID).exchangeProxy;
|
||||||
@ -105,6 +106,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -129,6 +131,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -157,6 +160,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -167,6 +171,7 @@ describe('DexSampler tests', () => {
|
|||||||
);
|
);
|
||||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||||
dexOrderSampler.getKyberSellQuotes(
|
dexOrderSampler.getKyberSellQuotes(
|
||||||
|
{ hintHandler: randomAddress(), networkProxy: randomAddress(), weth: randomAddress() },
|
||||||
new BigNumber(0),
|
new BigNumber(0),
|
||||||
expectedMakerToken,
|
expectedMakerToken,
|
||||||
expectedTakerToken,
|
expectedTakerToken,
|
||||||
@ -190,6 +195,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -234,6 +240,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -270,7 +277,7 @@ describe('DexSampler tests', () => {
|
|||||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleSellsFromEth2Dai: (takerToken, makerToken, fillAmounts) => {
|
sampleSellsFromEth2Dai: (_router, takerToken, makerToken, fillAmounts) => {
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
@ -278,6 +285,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -287,7 +295,12 @@ describe('DexSampler tests', () => {
|
|||||||
async () => undefined,
|
async () => undefined,
|
||||||
);
|
);
|
||||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||||
dexOrderSampler.getEth2DaiSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
|
dexOrderSampler.getEth2DaiSellQuotes(
|
||||||
|
randomAddress(),
|
||||||
|
expectedMakerToken,
|
||||||
|
expectedTakerToken,
|
||||||
|
expectedTakerFillAmounts,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
});
|
});
|
||||||
@ -298,7 +311,7 @@ describe('DexSampler tests', () => {
|
|||||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleSellsFromUniswap: (takerToken, makerToken, fillAmounts) => {
|
sampleSellsFromUniswap: (_router, takerToken, makerToken, fillAmounts) => {
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
@ -306,6 +319,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -315,7 +329,12 @@ describe('DexSampler tests', () => {
|
|||||||
async () => undefined,
|
async () => undefined,
|
||||||
);
|
);
|
||||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||||
dexOrderSampler.getUniswapSellQuotes(expectedMakerToken, expectedTakerToken, expectedTakerFillAmounts),
|
dexOrderSampler.getUniswapSellQuotes(
|
||||||
|
randomAddress(),
|
||||||
|
expectedMakerToken,
|
||||||
|
expectedTakerToken,
|
||||||
|
expectedTakerFillAmounts,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillableAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
});
|
});
|
||||||
@ -333,6 +352,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -357,7 +377,7 @@ describe('DexSampler tests', () => {
|
|||||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleBuysFromEth2Dai: (takerToken, makerToken, fillAmounts) => {
|
sampleBuysFromEth2Dai: (_router, takerToken, makerToken, fillAmounts) => {
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
@ -365,6 +385,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -374,7 +395,12 @@ describe('DexSampler tests', () => {
|
|||||||
async () => undefined,
|
async () => undefined,
|
||||||
);
|
);
|
||||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||||
dexOrderSampler.getEth2DaiBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
dexOrderSampler.getEth2DaiBuyQuotes(
|
||||||
|
randomAddress(),
|
||||||
|
expectedMakerToken,
|
||||||
|
expectedTakerToken,
|
||||||
|
expectedMakerFillAmounts,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
expect(fillableAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillableAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
});
|
});
|
||||||
@ -385,7 +411,7 @@ describe('DexSampler tests', () => {
|
|||||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 10);
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleBuysFromUniswap: (takerToken, makerToken, fillAmounts) => {
|
sampleBuysFromUniswap: (_router, takerToken, makerToken, fillAmounts) => {
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
@ -393,6 +419,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -402,7 +429,12 @@ describe('DexSampler tests', () => {
|
|||||||
async () => undefined,
|
async () => undefined,
|
||||||
);
|
);
|
||||||
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
const [fillableAmounts] = await dexOrderSampler.executeAsync(
|
||||||
dexOrderSampler.getUniswapBuyQuotes(expectedMakerToken, expectedTakerToken, expectedMakerFillAmounts),
|
dexOrderSampler.getUniswapBuyQuotes(
|
||||||
|
randomAddress(),
|
||||||
|
expectedMakerToken,
|
||||||
|
expectedTakerToken,
|
||||||
|
expectedMakerFillAmounts,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
expect(fillableAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillableAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
});
|
});
|
||||||
@ -423,21 +455,25 @@ describe('DexSampler tests', () => {
|
|||||||
};
|
};
|
||||||
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
const expectedTakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||||
let uniswapRouter: string;
|
let uniswapRouter: string;
|
||||||
|
let uniswapV2Router: string;
|
||||||
|
let eth2DaiRouter: string;
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleSellsFromUniswap: (takerToken, makerToken, fillAmounts) => {
|
sampleSellsFromUniswap: (router, takerToken, makerToken, fillAmounts) => {
|
||||||
|
uniswapRouter = router;
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
||||||
},
|
},
|
||||||
sampleSellsFromEth2Dai: (takerToken, makerToken, fillAmounts) => {
|
sampleSellsFromEth2Dai: (router, takerToken, makerToken, fillAmounts) => {
|
||||||
|
eth2DaiRouter = router;
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedTakerFillAmounts);
|
||||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Eth2Dai]).integerValue());
|
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Eth2Dai]).integerValue());
|
||||||
},
|
},
|
||||||
sampleSellsFromUniswapV2: (router, path, fillAmounts) => {
|
sampleSellsFromUniswapV2: (router, path, fillAmounts) => {
|
||||||
uniswapRouter = router;
|
uniswapV2Router = router;
|
||||||
if (path.length === 2) {
|
if (path.length === 2) {
|
||||||
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
||||||
} else if (path.length === 3) {
|
} else if (path.length === 3) {
|
||||||
@ -450,6 +486,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -471,10 +508,22 @@ describe('DexSampler tests', () => {
|
|||||||
source: s,
|
source: s,
|
||||||
input: a,
|
input: a,
|
||||||
output: a.times(ratesBySource[s]).integerValue(),
|
output: a.times(ratesBySource[s]).integerValue(),
|
||||||
fillData:
|
fillData: (() => {
|
||||||
s === ERC20BridgeSource.UniswapV2
|
if (s === ERC20BridgeSource.UniswapV2) {
|
||||||
? { router: uniswapRouter, tokenAddressPath: [expectedTakerToken, expectedMakerToken] }
|
return {
|
||||||
: {},
|
router: uniswapV2Router,
|
||||||
|
tokenAddressPath: [expectedTakerToken, expectedMakerToken],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (s === ERC20BridgeSource.Eth2Dai) {
|
||||||
|
return { router: eth2DaiRouter };
|
||||||
|
}
|
||||||
|
// TODO jacob pass through
|
||||||
|
if (s === ERC20BridgeSource.Uniswap) {
|
||||||
|
return { router: uniswapRouter };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
})(),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
const uniswapV2ETHQuotes = [
|
const uniswapV2ETHQuotes = [
|
||||||
@ -483,7 +532,7 @@ describe('DexSampler tests', () => {
|
|||||||
input: a,
|
input: a,
|
||||||
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
||||||
fillData: {
|
fillData: {
|
||||||
router: uniswapRouter,
|
router: uniswapV2Router,
|
||||||
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
@ -509,6 +558,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
new MockSamplerContract({}),
|
new MockSamplerContract({}),
|
||||||
undefined,
|
undefined,
|
||||||
balancerPoolsCache,
|
balancerPoolsCache,
|
||||||
@ -535,21 +585,25 @@ describe('DexSampler tests', () => {
|
|||||||
};
|
};
|
||||||
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
const expectedMakerFillAmounts = getSampleAmounts(new BigNumber(100e18), 3);
|
||||||
let uniswapRouter: string;
|
let uniswapRouter: string;
|
||||||
|
let uniswapV2Router: string;
|
||||||
|
let eth2DaiRouter: string;
|
||||||
const sampler = new MockSamplerContract({
|
const sampler = new MockSamplerContract({
|
||||||
sampleBuysFromUniswap: (takerToken, makerToken, fillAmounts) => {
|
sampleBuysFromUniswap: (router, takerToken, makerToken, fillAmounts) => {
|
||||||
|
uniswapRouter = router;
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Uniswap]).integerValue());
|
||||||
},
|
},
|
||||||
sampleBuysFromEth2Dai: (takerToken, makerToken, fillAmounts) => {
|
sampleBuysFromEth2Dai: (router, takerToken, makerToken, fillAmounts) => {
|
||||||
|
eth2DaiRouter = router;
|
||||||
expect(takerToken).to.eq(expectedTakerToken);
|
expect(takerToken).to.eq(expectedTakerToken);
|
||||||
expect(makerToken).to.eq(expectedMakerToken);
|
expect(makerToken).to.eq(expectedMakerToken);
|
||||||
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
expect(fillAmounts).to.deep.eq(expectedMakerFillAmounts);
|
||||||
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Eth2Dai]).integerValue());
|
return fillAmounts.map(a => a.times(ratesBySource[ERC20BridgeSource.Eth2Dai]).integerValue());
|
||||||
},
|
},
|
||||||
sampleBuysFromUniswapV2: (router, path, fillAmounts) => {
|
sampleBuysFromUniswapV2: (router, path, fillAmounts) => {
|
||||||
uniswapRouter = router;
|
uniswapV2Router = router;
|
||||||
if (path.length === 2) {
|
if (path.length === 2) {
|
||||||
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
expect(path).to.deep.eq([expectedTakerToken, expectedMakerToken]);
|
||||||
} else if (path.length === 3) {
|
} else if (path.length === 3) {
|
||||||
@ -562,6 +616,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
@ -578,10 +633,21 @@ describe('DexSampler tests', () => {
|
|||||||
source: s,
|
source: s,
|
||||||
input: a,
|
input: a,
|
||||||
output: a.times(ratesBySource[s]).integerValue(),
|
output: a.times(ratesBySource[s]).integerValue(),
|
||||||
fillData:
|
fillData: (() => {
|
||||||
s === ERC20BridgeSource.UniswapV2
|
if (s === ERC20BridgeSource.UniswapV2) {
|
||||||
? { router: uniswapRouter, tokenAddressPath: [expectedTakerToken, expectedMakerToken] }
|
return {
|
||||||
: {},
|
router: uniswapV2Router,
|
||||||
|
tokenAddressPath: [expectedTakerToken, expectedMakerToken],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (s === ERC20BridgeSource.Eth2Dai) {
|
||||||
|
return { router: eth2DaiRouter };
|
||||||
|
}
|
||||||
|
if (s === ERC20BridgeSource.Uniswap) {
|
||||||
|
return { router: uniswapRouter };
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
})(),
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
const uniswapV2ETHQuotes = [
|
const uniswapV2ETHQuotes = [
|
||||||
@ -590,7 +656,7 @@ describe('DexSampler tests', () => {
|
|||||||
input: a,
|
input: a,
|
||||||
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
output: a.times(ratesBySource[ERC20BridgeSource.UniswapV2]).integerValue(),
|
||||||
fillData: {
|
fillData: {
|
||||||
router: uniswapRouter,
|
router: uniswapV2Router,
|
||||||
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
tokenAddressPath: [expectedTakerToken, wethAddress, expectedMakerToken],
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
@ -612,6 +678,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
new MockSamplerContract({}),
|
new MockSamplerContract({}),
|
||||||
undefined,
|
undefined,
|
||||||
balancerPoolsCache,
|
balancerPoolsCache,
|
||||||
@ -646,6 +713,7 @@ describe('DexSampler tests', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const dexOrderSampler = new DexOrderSampler(
|
const dexOrderSampler = new DexOrderSampler(
|
||||||
|
chainId,
|
||||||
sampler,
|
sampler,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
|
@ -19,9 +19,9 @@ import { NativeOrderWithFillableAmounts } from '../src/types';
|
|||||||
import { MarketOperationUtils } from '../src/utils/market_operation_utils/';
|
import { MarketOperationUtils } from '../src/utils/market_operation_utils/';
|
||||||
import { BalancerPoolsCache } from '../src/utils/market_operation_utils/balancer_utils';
|
import { BalancerPoolsCache } from '../src/utils/market_operation_utils/balancer_utils';
|
||||||
import {
|
import {
|
||||||
BUY_SOURCE_FILTER,
|
BUY_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
POSITIVE_INF,
|
POSITIVE_INF,
|
||||||
SELL_SOURCE_FILTER,
|
SELL_SOURCE_FILTER_BY_CHAIN_ID,
|
||||||
SOURCE_FLAGS,
|
SOURCE_FLAGS,
|
||||||
} from '../src/utils/market_operation_utils/constants';
|
} from '../src/utils/market_operation_utils/constants';
|
||||||
import { CreamPoolsCache } from '../src/utils/market_operation_utils/cream_utils';
|
import { CreamPoolsCache } from '../src/utils/market_operation_utils/cream_utils';
|
||||||
@ -65,9 +65,11 @@ const DEFAULT_EXCLUDED = [
|
|||||||
ERC20BridgeSource.LiquidityProvider,
|
ERC20BridgeSource.LiquidityProvider,
|
||||||
ERC20BridgeSource.CryptoCom,
|
ERC20BridgeSource.CryptoCom,
|
||||||
ERC20BridgeSource.Linkswap,
|
ERC20BridgeSource.Linkswap,
|
||||||
|
ERC20BridgeSource.PancakeSwap,
|
||||||
|
ERC20BridgeSource.BakerySwap,
|
||||||
];
|
];
|
||||||
const BUY_SOURCES = BUY_SOURCE_FILTER.sources;
|
const BUY_SOURCES = BUY_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
|
||||||
const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
|
const SELL_SOURCES = SELL_SOURCE_FILTER_BY_CHAIN_ID[ChainId.Mainnet].sources;
|
||||||
const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = { default: [] };
|
const TOKEN_ADJACENCY_GRAPH: TokenAdjacencyGraph = { default: [] };
|
||||||
|
|
||||||
const SIGNATURE = { v: 1, r: NULL_BYTES, s: NULL_BYTES, signatureType: SignatureType.EthSign };
|
const SIGNATURE = { v: 1, r: NULL_BYTES, s: NULL_BYTES, signatureType: SignatureType.EthSign };
|
||||||
@ -301,6 +303,8 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.DodoV2]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.DodoV2]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.CryptoCom]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.CryptoCom]: _.times(NUM_SAMPLES, () => 0),
|
||||||
[ERC20BridgeSource.Linkswap]: _.times(NUM_SAMPLES, () => 0),
|
[ERC20BridgeSource.Linkswap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.PancakeSwap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
|
[ERC20BridgeSource.BakerySwap]: _.times(NUM_SAMPLES, () => 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_RATES: RatesBySource = {
|
const DEFAULT_RATES: RatesBySource = {
|
||||||
@ -318,7 +322,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.UniswapV2]: { tokenAddressPath: [] },
|
[ERC20BridgeSource.UniswapV2]: { tokenAddressPath: [] },
|
||||||
[ERC20BridgeSource.Balancer]: { poolAddress: randomAddress() },
|
[ERC20BridgeSource.Balancer]: { poolAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Bancor]: { path: [], networkAddress: randomAddress() },
|
[ERC20BridgeSource.Bancor]: { path: [], networkAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Kyber]: { hint: '0x', reserveId: '0x' },
|
[ERC20BridgeSource.Kyber]: { hint: '0x', reserveId: '0x', networkAddress: randomAddress() },
|
||||||
[ERC20BridgeSource.Curve]: {
|
[ERC20BridgeSource.Curve]: {
|
||||||
pool: {
|
pool: {
|
||||||
poolAddress: randomAddress(),
|
poolAddress: randomAddress(),
|
||||||
@ -363,6 +367,8 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
[ERC20BridgeSource.DodoV2]: {},
|
[ERC20BridgeSource.DodoV2]: {},
|
||||||
[ERC20BridgeSource.CryptoCom]: { tokenAddressPath: [] },
|
[ERC20BridgeSource.CryptoCom]: { tokenAddressPath: [] },
|
||||||
[ERC20BridgeSource.Linkswap]: { tokenAddressPath: [] },
|
[ERC20BridgeSource.Linkswap]: { tokenAddressPath: [] },
|
||||||
|
[ERC20BridgeSource.Uniswap]: { router: randomAddress() },
|
||||||
|
[ERC20BridgeSource.Eth2Dai]: { router: randomAddress() },
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_OPS = {
|
const DEFAULT_OPS = {
|
||||||
@ -441,6 +447,7 @@ describe('MarketOperationUtils tests', () => {
|
|||||||
balancerPoolsCache: new BalancerPoolsCache(),
|
balancerPoolsCache: new BalancerPoolsCache(),
|
||||||
creamPoolsCache: new CreamPoolsCache(),
|
creamPoolsCache: new CreamPoolsCache(),
|
||||||
liquidityProviderRegistry: {},
|
liquidityProviderRegistry: {},
|
||||||
|
chainId: CHAIN_ID,
|
||||||
} as any) as DexOrderSampler;
|
} as any) as DexOrderSampler;
|
||||||
|
|
||||||
function replaceSamplerOps(ops: Partial<typeof DEFAULT_OPS> = {}): void {
|
function replaceSamplerOps(ops: Partial<typeof DEFAULT_OPS> = {}): void {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { ContractTxFunctionObj } from '@0x/base-contract';
|
import { ContractTxFunctionObj } from '@0x/base-contract';
|
||||||
import { constants } from '@0x/contracts-test-utils';
|
import { constants } from '@0x/contracts-test-utils';
|
||||||
import { LimitOrderFields, Signature } from '@0x/protocol-utils';
|
import { LimitOrderFields, Signature } from '@0x/protocol-utils';
|
||||||
import { BigNumber, hexUtils } from '@0x/utils';
|
import { BigNumber, hexUtils, NULL_BYTES } from '@0x/utils';
|
||||||
|
|
||||||
import { SamplerCallResult } from '../../src/types';
|
import { SamplerCallResult } from '../../src/types';
|
||||||
|
import { KyberSamplerOpts } from '../../src/utils/market_operation_utils/types';
|
||||||
import { ERC20BridgeSamplerContract } from '../../src/wrappers';
|
import { ERC20BridgeSamplerContract } from '../../src/wrappers';
|
||||||
|
|
||||||
export type GetOrderFillableAssetAmountResult = BigNumber[];
|
export type GetOrderFillableAssetAmountResult = BigNumber[];
|
||||||
@ -14,18 +15,32 @@ export type GetOrderFillableAssetAmountHandler = (
|
|||||||
) => GetOrderFillableAssetAmountResult;
|
) => GetOrderFillableAssetAmountResult;
|
||||||
|
|
||||||
export type SampleResults = BigNumber[];
|
export type SampleResults = BigNumber[];
|
||||||
export type SampleSellsHandler = (
|
export type SampleSellsUniswapHandler = (
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerTokenAmounts: BigNumber[],
|
takerTokenAmounts: BigNumber[],
|
||||||
) => SampleResults;
|
) => SampleResults;
|
||||||
export type SampleBuysHandler = (
|
export type SampleBuysUniswapHandler = (
|
||||||
|
router: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
makerTokenAmounts: BigNumber[],
|
||||||
|
) => SampleResults;
|
||||||
|
export type SampleSellsEth2DaiHandler = (
|
||||||
|
router: string,
|
||||||
|
takerToken: string,
|
||||||
|
makerToken: string,
|
||||||
|
takerTokenAmounts: BigNumber[],
|
||||||
|
) => SampleResults;
|
||||||
|
export type SampleBuysEth2DaiHandler = (
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
makerTokenAmounts: BigNumber[],
|
makerTokenAmounts: BigNumber[],
|
||||||
) => SampleResults;
|
) => SampleResults;
|
||||||
export type SampleSellsKyberHandler = (
|
export type SampleSellsKyberHandler = (
|
||||||
reserveOffset: BigNumber,
|
opts: KyberSamplerOpts,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerTokenAmounts: BigNumber[],
|
takerTokenAmounts: BigNumber[],
|
||||||
@ -57,11 +72,11 @@ interface Handlers {
|
|||||||
getLimitOrderFillableTakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
getLimitOrderFillableTakerAssetAmounts: GetOrderFillableAssetAmountHandler;
|
||||||
sampleSellsFromKyberNetwork: SampleSellsKyberHandler;
|
sampleSellsFromKyberNetwork: SampleSellsKyberHandler;
|
||||||
sampleSellsFromLiquidityProvider: SampleSellsLPHandler;
|
sampleSellsFromLiquidityProvider: SampleSellsLPHandler;
|
||||||
sampleSellsFromEth2Dai: SampleSellsHandler;
|
sampleSellsFromEth2Dai: SampleSellsEth2DaiHandler;
|
||||||
sampleSellsFromUniswap: SampleSellsHandler;
|
sampleSellsFromUniswap: SampleSellsUniswapHandler;
|
||||||
sampleSellsFromUniswapV2: SampleUniswapV2Handler;
|
sampleSellsFromUniswapV2: SampleUniswapV2Handler;
|
||||||
sampleBuysFromEth2Dai: SampleBuysHandler;
|
sampleBuysFromEth2Dai: SampleBuysEth2DaiHandler;
|
||||||
sampleBuysFromUniswap: SampleBuysHandler;
|
sampleBuysFromUniswap: SampleBuysUniswapHandler;
|
||||||
sampleBuysFromUniswapV2: SampleUniswapV2Handler;
|
sampleBuysFromUniswapV2: SampleUniswapV2Handler;
|
||||||
sampleBuysFromLiquidityProvider: SampleSellsLPHandler;
|
sampleBuysFromLiquidityProvider: SampleSellsLPHandler;
|
||||||
}
|
}
|
||||||
@ -111,7 +126,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sampleSellsFromKyberNetwork(
|
public sampleSellsFromKyberNetwork(
|
||||||
reserveOffset: BigNumber,
|
opts: KyberSamplerOpts,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerAssetAmounts: BigNumber[],
|
takerAssetAmounts: BigNumber[],
|
||||||
@ -119,7 +134,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
return this._wrapCall(
|
return this._wrapCall(
|
||||||
super.sampleSellsFromKyberNetwork,
|
super.sampleSellsFromKyberNetwork,
|
||||||
this._handlers.sampleSellsFromKyberNetwork,
|
this._handlers.sampleSellsFromKyberNetwork,
|
||||||
reserveOffset,
|
{ ...opts, reserveOffset: new BigNumber(1), hint: NULL_BYTES },
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerAssetAmounts,
|
takerAssetAmounts,
|
||||||
@ -127,6 +142,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sampleSellsFromEth2Dai(
|
public sampleSellsFromEth2Dai(
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerAssetAmounts: BigNumber[],
|
takerAssetAmounts: BigNumber[],
|
||||||
@ -134,6 +150,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
return this._wrapCall(
|
return this._wrapCall(
|
||||||
super.sampleSellsFromEth2Dai,
|
super.sampleSellsFromEth2Dai,
|
||||||
this._handlers.sampleSellsFromEth2Dai,
|
this._handlers.sampleSellsFromEth2Dai,
|
||||||
|
router,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerAssetAmounts,
|
takerAssetAmounts,
|
||||||
@ -141,6 +158,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sampleSellsFromUniswap(
|
public sampleSellsFromUniswap(
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
takerAssetAmounts: BigNumber[],
|
takerAssetAmounts: BigNumber[],
|
||||||
@ -148,6 +166,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
return this._wrapCall(
|
return this._wrapCall(
|
||||||
super.sampleSellsFromUniswap,
|
super.sampleSellsFromUniswap,
|
||||||
this._handlers.sampleSellsFromUniswap,
|
this._handlers.sampleSellsFromUniswap,
|
||||||
|
router,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
takerAssetAmounts,
|
takerAssetAmounts,
|
||||||
@ -185,6 +204,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sampleBuysFromEth2Dai(
|
public sampleBuysFromEth2Dai(
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
makerAssetAmounts: BigNumber[],
|
makerAssetAmounts: BigNumber[],
|
||||||
@ -192,6 +212,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
return this._wrapCall(
|
return this._wrapCall(
|
||||||
super.sampleBuysFromEth2Dai,
|
super.sampleBuysFromEth2Dai,
|
||||||
this._handlers.sampleBuysFromEth2Dai,
|
this._handlers.sampleBuysFromEth2Dai,
|
||||||
|
router,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
makerAssetAmounts,
|
makerAssetAmounts,
|
||||||
@ -199,6 +220,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public sampleBuysFromUniswap(
|
public sampleBuysFromUniswap(
|
||||||
|
router: string,
|
||||||
takerToken: string,
|
takerToken: string,
|
||||||
makerToken: string,
|
makerToken: string,
|
||||||
makerAssetAmounts: BigNumber[],
|
makerAssetAmounts: BigNumber[],
|
||||||
@ -206,6 +228,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
|
|||||||
return this._wrapCall(
|
return this._wrapCall(
|
||||||
super.sampleBuysFromUniswap,
|
super.sampleBuysFromUniswap,
|
||||||
this._handlers.sampleBuysFromUniswap,
|
this._handlers.sampleBuysFromUniswap,
|
||||||
|
router,
|
||||||
takerToken,
|
takerToken,
|
||||||
makerToken,
|
makerToken,
|
||||||
makerAssetAmounts,
|
makerAssetAmounts,
|
||||||
|
@ -43,7 +43,7 @@ export const testHelpers = {
|
|||||||
afterResponseCallback: () => Promise<void>,
|
afterResponseCallback: () => Promise<void>,
|
||||||
axiosClient: AxiosInstance = axios,
|
axiosClient: AxiosInstance = axios,
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
const mockedAxios = new AxiosMockAdapter(axiosClient, { onNoMatch: 'throwException' });
|
const mockedAxios = new AxiosMockAdapter(axiosClient, { onNoMatch: 'throwException' } as any);
|
||||||
try {
|
try {
|
||||||
// Mock out Standard RFQ-T/M responses
|
// Mock out Standard RFQ-T/M responses
|
||||||
for (const mockedResponse of standardMockedResponses) {
|
for (const mockedResponse of standardMockedResponses) {
|
||||||
|
@ -10,7 +10,6 @@ export * from '../test/generated-wrappers/bancor_sampler';
|
|||||||
export * from '../test/generated-wrappers/curve_sampler';
|
export * from '../test/generated-wrappers/curve_sampler';
|
||||||
export * from '../test/generated-wrappers/d_o_d_o_sampler';
|
export * from '../test/generated-wrappers/d_o_d_o_sampler';
|
||||||
export * from '../test/generated-wrappers/d_o_d_o_v2_sampler';
|
export * from '../test/generated-wrappers/d_o_d_o_v2_sampler';
|
||||||
export * from '../test/generated-wrappers/deployment_constants';
|
|
||||||
export * from '../test/generated-wrappers/dummy_liquidity_provider';
|
export * from '../test/generated-wrappers/dummy_liquidity_provider';
|
||||||
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
export * from '../test/generated-wrappers/erc20_bridge_sampler';
|
||||||
export * from '../test/generated-wrappers/eth2_dai_sampler';
|
export * from '../test/generated-wrappers/eth2_dai_sampler';
|
||||||
@ -34,7 +33,6 @@ 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/shell_sampler';
|
export * from '../test/generated-wrappers/shell_sampler';
|
||||||
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';
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
"test/generated-artifacts/CurveSampler.json",
|
"test/generated-artifacts/CurveSampler.json",
|
||||||
"test/generated-artifacts/DODOSampler.json",
|
"test/generated-artifacts/DODOSampler.json",
|
||||||
"test/generated-artifacts/DODOV2Sampler.json",
|
"test/generated-artifacts/DODOV2Sampler.json",
|
||||||
"test/generated-artifacts/DeploymentConstants.json",
|
|
||||||
"test/generated-artifacts/DummyLiquidityProvider.json",
|
"test/generated-artifacts/DummyLiquidityProvider.json",
|
||||||
"test/generated-artifacts/ERC20BridgeSampler.json",
|
"test/generated-artifacts/ERC20BridgeSampler.json",
|
||||||
"test/generated-artifacts/Eth2DaiSampler.json",
|
"test/generated-artifacts/Eth2DaiSampler.json",
|
||||||
@ -37,7 +36,6 @@
|
|||||||
"test/generated-artifacts/NativeOrderSampler.json",
|
"test/generated-artifacts/NativeOrderSampler.json",
|
||||||
"test/generated-artifacts/SamplerUtils.json",
|
"test/generated-artifacts/SamplerUtils.json",
|
||||||
"test/generated-artifacts/ShellSampler.json",
|
"test/generated-artifacts/ShellSampler.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",
|
||||||
|
@ -1,4 +1,21 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "6.0.0-bsc.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Add BSC chain addresses",
|
||||||
|
"pr": 164
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Remove exchangeProxyAllowanceTarget",
|
||||||
|
"pr": 164
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"note": "Redeployed FQT on BSC",
|
||||||
|
"pr": 181
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "5.11.0",
|
"version": "5.11.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
"dexForwarderBridge": "0xc47b7094f378e54347e281aab170e8cca69d880a",
|
"dexForwarderBridge": "0xc47b7094f378e54347e281aab170e8cca69d880a",
|
||||||
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
||||||
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
||||||
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
|
|
||||||
"exchangeProxyTransformerDeployer": "0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb",
|
"exchangeProxyTransformerDeployer": "0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb",
|
||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"exchangeProxyLiquidityProviderSandbox": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
"exchangeProxyLiquidityProviderSandbox": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
|
||||||
@ -71,7 +70,6 @@
|
|||||||
"dexForwarderBridge": "0x3261ea1411a1a840aed708896f779e1b837c917e",
|
"dexForwarderBridge": "0x3261ea1411a1a840aed708896f779e1b837c917e",
|
||||||
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
||||||
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
||||||
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
|
|
||||||
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
|
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
|
||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"exchangeProxyLiquidityProviderSandbox": "0x53a3a41047ae6f6a593df847e3bb287ecd3ac825",
|
"exchangeProxyLiquidityProviderSandbox": "0x53a3a41047ae6f6a593df847e3bb287ecd3ac825",
|
||||||
@ -113,7 +111,6 @@
|
|||||||
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
||||||
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
||||||
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
|
|
||||||
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
|
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
|
||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"exchangeProxyLiquidityProviderSandbox": "0x2e2090562076197f94f8d1beac0963b6d4c118b6",
|
"exchangeProxyLiquidityProviderSandbox": "0x2e2090562076197f94f8d1beac0963b6d4c118b6",
|
||||||
@ -155,7 +152,6 @@
|
|||||||
"dexForwarderBridge": "0x985d1a95c6a86a3bf85c4d425af984abceaf01de",
|
"dexForwarderBridge": "0x985d1a95c6a86a3bf85c4d425af984abceaf01de",
|
||||||
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
|
||||||
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
||||||
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
|
|
||||||
"exchangeProxyTransformerDeployer": "0x1b62de2dbb5e7aa519e9c442721ecef75702807f",
|
"exchangeProxyTransformerDeployer": "0x1b62de2dbb5e7aa519e9c442721ecef75702807f",
|
||||||
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
|
||||||
"exchangeProxyLiquidityProviderSandbox": "0x4022e3982f326455f0905de3dbc4449999baf2dc",
|
"exchangeProxyLiquidityProviderSandbox": "0x4022e3982f326455f0905de3dbc4449999baf2dc",
|
||||||
@ -167,6 +163,47 @@
|
|||||||
"positiveSlippageFeeTransformer": "0x0000000000000000000000000000000000000000"
|
"positiveSlippageFeeTransformer": "0x0000000000000000000000000000000000000000"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"56": {
|
||||||
|
"erc20Proxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc721Proxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zrxToken": "0x0000000000000000000000000000000000000000",
|
||||||
|
"etherToken": "0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
|
||||||
|
"exchangeV2": "0x0000000000000000000000000000000000000000",
|
||||||
|
"exchange": "0x0000000000000000000000000000000000000000",
|
||||||
|
"assetProxyOwner": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zeroExGovernor": "0x0000000000000000000000000000000000000000",
|
||||||
|
"forwarder": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinatorRegistry": "0x0000000000000000000000000000000000000000",
|
||||||
|
"coordinator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"multiAssetProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"staticCallProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc1155Proxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"devUtils": "0x0000000000000000000000000000000000000000",
|
||||||
|
"zrxVault": "0x0000000000000000000000000000000000000000",
|
||||||
|
"staking": "0x0000000000000000000000000000000000000000",
|
||||||
|
"stakingProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc20BridgeProxy": "0x0000000000000000000000000000000000000000",
|
||||||
|
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
|
||||||
|
"chaiBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dydxBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"godsUnchainedValidator": "0x0000000000000000000000000000000000000000",
|
||||||
|
"broker": "0x0000000000000000000000000000000000000000",
|
||||||
|
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
|
||||||
|
"maximumGasPrice": "0x0000000000000000000000000000000000000000",
|
||||||
|
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
||||||
|
"exchangeProxyGovernor": "0xccc9769c1a58766e79423a34b2cc5052d65c1983",
|
||||||
|
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
|
||||||
|
"exchangeProxyTransformerDeployer": "0x8224aa8fe5c9f07d5a59c735386ff6cc6aaeb568",
|
||||||
|
"exchangeProxyFlashWallet": "0xdb6f1920a889355780af7570773609bd8cb1f498",
|
||||||
|
"exchangeProxyLiquidityProviderSandbox": "0xde7b2747624a647600fdb349184d0448ab954929",
|
||||||
|
"transformers": {
|
||||||
|
"wethTransformer": "0xac3d95668c092e895cd83a9cbafe9c7d9906471f",
|
||||||
|
"payTakerTransformer": "0x4f5e8ca2cadecd4a467ae441e4b03de4278a4574",
|
||||||
|
"affiliateFeeTransformer": "0x1be34ab9b2acb5c4ddd89454bdce637967e65230",
|
||||||
|
"fillQuoteTransformer": "0xfa8ca57cb24cd59e74ae1659a00104188e7e8a3e",
|
||||||
|
"positiveSlippageFeeTransformer": "0x7f5c79ad1788573b1145f4651a248523c54f5d1f"
|
||||||
|
}
|
||||||
|
},
|
||||||
"1337": {
|
"1337": {
|
||||||
"erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
"erc20Proxy": "0x1dc4c1cefef38a777b15aa20260a54e584b16c48",
|
||||||
"erc721Proxy": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
|
"erc721Proxy": "0x1d7022f5b17d2f8b695918fb48fa1089c9f85401",
|
||||||
@ -197,16 +234,15 @@
|
|||||||
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
|
||||||
"exchangeProxyGovernor": "0x0000000000000000000000000000000000000000",
|
"exchangeProxyGovernor": "0x0000000000000000000000000000000000000000",
|
||||||
"exchangeProxy": "0x5315e44798395d4a952530d131249fe00f554565",
|
"exchangeProxy": "0x5315e44798395d4a952530d131249fe00f554565",
|
||||||
"exchangeProxyAllowanceTarget": "0x8362c3ebd90041b30ec45908332e592721642637",
|
|
||||||
"exchangeProxyTransformerDeployer": "0x5409ed021d9299bf6814279a6a1411a7e866a631",
|
"exchangeProxyTransformerDeployer": "0x5409ed021d9299bf6814279a6a1411a7e866a631",
|
||||||
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
|
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
|
||||||
"exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
|
"exchangeProxyLiquidityProviderSandbox": "0x0000000000000000000000000000000000000000",
|
||||||
"transformers": {
|
"transformers": {
|
||||||
"wethTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3",
|
"wethTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5",
|
||||||
"payTakerTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a",
|
"payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3",
|
||||||
"affiliateFeeTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db",
|
"affiliateFeeTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a",
|
||||||
"fillQuoteTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace",
|
"fillQuoteTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db",
|
||||||
"positiveSlippageFeeTransformer": "0xdd66c23e07b4d6925b6089b5fe6fc9e62941afe8"
|
"positiveSlippageFeeTransformer": "0x45b3a72221e571017c0f0ec42189e11d149d0ace"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ export interface ContractAddresses {
|
|||||||
dexForwarderBridge: string;
|
dexForwarderBridge: string;
|
||||||
exchangeProxyGovernor: string;
|
exchangeProxyGovernor: string;
|
||||||
exchangeProxy: string;
|
exchangeProxy: string;
|
||||||
exchangeProxyAllowanceTarget: string;
|
|
||||||
exchangeProxyTransformerDeployer: string;
|
exchangeProxyTransformerDeployer: string;
|
||||||
exchangeProxyFlashWallet: string;
|
exchangeProxyFlashWallet: string;
|
||||||
exchangeProxyLiquidityProviderSandbox: string;
|
exchangeProxyLiquidityProviderSandbox: string;
|
||||||
@ -49,6 +48,7 @@ export enum ChainId {
|
|||||||
Rinkeby = 4,
|
Rinkeby = 4,
|
||||||
Kovan = 42,
|
Kovan = 42,
|
||||||
Ganache = 1337,
|
Ganache = 1337,
|
||||||
|
BSC = 56,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "3.14.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Update artifacts",
|
||||||
|
"pr": 164
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "3.13.0",
|
"version": "3.13.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -284,18 +284,6 @@
|
|||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{ "internalType": "contract IERC20TokenV06", "name": "token", "type": "address" },
|
|
||||||
{ "internalType": "address", "name": "owner", "type": "address" },
|
|
||||||
{ "internalType": "address", "name": "to", "type": "address" },
|
|
||||||
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
|
|
||||||
],
|
|
||||||
"name": "_spendERC20Tokens",
|
|
||||||
"outputs": [],
|
|
||||||
"stateMutability": "nonpayable",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -973,13 +961,6 @@
|
|||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"inputs": [],
|
|
||||||
"name": "getAllowanceTarget",
|
|
||||||
"outputs": [{ "internalType": "address", "name": "target", "type": "address" }],
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -1302,16 +1283,6 @@
|
|||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"inputs": [
|
|
||||||
{ "internalType": "contract IERC20TokenV06", "name": "token", "type": "address" },
|
|
||||||
{ "internalType": "address", "name": "owner", "type": "address" }
|
|
||||||
],
|
|
||||||
"name": "getSpendableERC20BalanceOf",
|
|
||||||
"outputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }],
|
|
||||||
"stateMutability": "view",
|
|
||||||
"type": "function"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"inputs": [],
|
"inputs": [],
|
||||||
"name": "getTransformWallet",
|
"name": "getTransformWallet",
|
||||||
@ -1406,6 +1377,18 @@
|
|||||||
"stateMutability": "payable",
|
"stateMutability": "payable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{ "internalType": "contract IERC20TokenV06[]", "name": "tokens", "type": "address[]" },
|
||||||
|
{ "internalType": "uint256", "name": "sellAmount", "type": "uint256" },
|
||||||
|
{ "internalType": "uint256", "name": "minBuyAmount", "type": "uint256" },
|
||||||
|
{ "internalType": "enum IPancakeSwapFeature.ProtocolFork", "name": "fork", "type": "uint8" }
|
||||||
|
],
|
||||||
|
"name": "sellToPancakeSwap",
|
||||||
|
"outputs": [{ "internalType": "uint256", "name": "buyAmount", "type": "uint256" }],
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{ "internalType": "contract IERC20TokenV06[]", "name": "tokens", "type": "address[]" },
|
{ "internalType": "contract IERC20TokenV06[]", "name": "tokens", "type": "address[]" },
|
||||||
@ -1499,15 +1482,6 @@
|
|||||||
"takerTokenFilledAmount": "How much maker token was filled."
|
"takerTokenFilledAmount": "How much maker token was filled."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"_spendERC20Tokens(address,address,address,uint256)": {
|
|
||||||
"details": "Transfers ERC20 tokens from `owner` to `to`. Only callable from within.",
|
|
||||||
"params": {
|
|
||||||
"amount": "The amount of `token` to transfer.",
|
|
||||||
"owner": "The owner of the tokens.",
|
|
||||||
"to": "The recipient of the tokens.",
|
|
||||||
"token": "The token to spend."
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"_transformERC20((address,address,address,uint256,uint256,(uint32,bytes)[]))": {
|
"_transformERC20((address,address,address,uint256,uint256,(uint32,bytes)[]))": {
|
||||||
"details": "Internal version of `transformERC20()`. Only callable from within.",
|
"details": "Internal version of `transformERC20()`. Only callable from within.",
|
||||||
"params": { "args": "A `TransformERC20Args` struct." },
|
"params": { "args": "A `TransformERC20Args` struct." },
|
||||||
@ -1679,10 +1653,6 @@
|
|||||||
"takerTokenFilledAmount": "How much maker token was filled."
|
"takerTokenFilledAmount": "How much maker token was filled."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"getAllowanceTarget()": {
|
|
||||||
"details": "Get the address of the allowance target.",
|
|
||||||
"returns": { "target": "The target of token allowances." }
|
|
||||||
},
|
|
||||||
"getLimitOrderHash((address,address,uint128,uint128,uint128,address,address,address,address,bytes32,uint64,uint256))": {
|
"getLimitOrderHash((address,address,uint128,uint128,uint128,address,address,address,address,bytes32,uint64,uint256))": {
|
||||||
"details": "Get the canonical hash of a limit order.",
|
"details": "Get the canonical hash of a limit order.",
|
||||||
"params": { "order": "The limit order." },
|
"params": { "order": "The limit order." },
|
||||||
@ -1756,11 +1726,6 @@
|
|||||||
"rollbackLength": "The number of items in the rollback history for the function."
|
"rollbackLength": "The number of items in the rollback history for the function."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"getSpendableERC20BalanceOf(address,address)": {
|
|
||||||
"details": "Gets the maximum amount of an ERC20 token `token` that can be pulled from `owner`.",
|
|
||||||
"params": { "owner": "The owner of the tokens.", "token": "The token to spend." },
|
|
||||||
"returns": { "amount": "The amount of tokens that can be pulled." }
|
|
||||||
},
|
|
||||||
"getTransformWallet()": {
|
"getTransformWallet()": {
|
||||||
"details": "Return the current wallet instance that will serve as the execution context for transformations.",
|
"details": "Return the current wallet instance that will serve as the execution context for transformations.",
|
||||||
"returns": { "wallet": "The wallet instance." }
|
"returns": { "wallet": "The wallet instance." }
|
||||||
@ -1816,6 +1781,16 @@
|
|||||||
},
|
},
|
||||||
"returns": { "boughtAmount": "The amount of `outputToken` bought." }
|
"returns": { "boughtAmount": "The amount of `outputToken` bought." }
|
||||||
},
|
},
|
||||||
|
"sellToPancakeSwap(address[],uint256,uint256,uint8)": {
|
||||||
|
"details": "Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap.",
|
||||||
|
"params": {
|
||||||
|
"fork": "The protocol fork to use.",
|
||||||
|
"minBuyAmount": "Minimum amount of `tokens[-1]` to buy.",
|
||||||
|
"sellAmount": "of `tokens[0]` Amount to sell.",
|
||||||
|
"tokens": "Sell path."
|
||||||
|
},
|
||||||
|
"returns": { "buyAmount": "Amount of `tokens[-1]` bought." }
|
||||||
|
},
|
||||||
"sellToUniswap(address[],uint256,uint256,bool)": {
|
"sellToUniswap(address[],uint256,uint256,bool)": {
|
||||||
"details": "Efficiently sell directly to uniswap/sushiswap.",
|
"details": "Efficiently sell directly to uniswap/sushiswap.",
|
||||||
"params": {
|
"params": {
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "13.15.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Regenerate wrappers",
|
||||||
|
"pr": 164
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "13.14.0",
|
"version": "13.14.0",
|
||||||
"changes": [
|
"changes": [
|
||||||
|
@ -910,30 +910,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
stateMutability: 'nonpayable',
|
stateMutability: 'nonpayable',
|
||||||
type: 'function',
|
type: 'function',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
name: 'token',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'owner',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'to',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: '_spendERC20Tokens',
|
|
||||||
outputs: [],
|
|
||||||
stateMutability: 'nonpayable',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@ -2314,18 +2290,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
stateMutability: 'nonpayable',
|
stateMutability: 'nonpayable',
|
||||||
type: 'function',
|
type: 'function',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
inputs: [],
|
|
||||||
name: 'getAllowanceTarget',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
name: 'target',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@ -3017,27 +2981,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
stateMutability: 'view',
|
stateMutability: 'view',
|
||||||
type: 'function',
|
type: 'function',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
inputs: [
|
|
||||||
{
|
|
||||||
name: 'token',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'owner',
|
|
||||||
type: 'address',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
name: 'getSpendableERC20BalanceOf',
|
|
||||||
outputs: [
|
|
||||||
{
|
|
||||||
name: 'amount',
|
|
||||||
type: 'uint256',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
stateMutability: 'view',
|
|
||||||
type: 'function',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
inputs: [],
|
inputs: [],
|
||||||
name: 'getTransformWallet',
|
name: 'getTransformWallet',
|
||||||
@ -3212,6 +3155,35 @@ export class IZeroExContract extends BaseContract {
|
|||||||
stateMutability: 'payable',
|
stateMutability: 'payable',
|
||||||
type: 'function',
|
type: 'function',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'tokens',
|
||||||
|
type: 'address[]',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sellAmount',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'minBuyAmount',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fork',
|
||||||
|
type: 'uint8',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
name: 'sellToPancakeSwap',
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'buyAmount',
|
||||||
|
type: 'uint256',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
stateMutability: 'payable',
|
||||||
|
type: 'function',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@ -3581,69 +3553,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Transfers ERC20 tokens from `owner` to `to`.
|
|
||||||
* Only callable from within.
|
|
||||||
* @param token The token to spend.
|
|
||||||
* @param owner The owner of the tokens.
|
|
||||||
* @param to The recipient of the tokens.
|
|
||||||
* @param amount The amount of `token` to transfer.
|
|
||||||
*/
|
|
||||||
public _spendERC20Tokens(token: string, owner: string, to: string, amount: BigNumber): ContractTxFunctionObj<void> {
|
|
||||||
const self = (this as any) as IZeroExContract;
|
|
||||||
assert.isString('token', token);
|
|
||||||
assert.isString('owner', owner);
|
|
||||||
assert.isString('to', to);
|
|
||||||
assert.isBigNumber('amount', amount);
|
|
||||||
const functionSignature = '_spendERC20Tokens(address,address,address,uint256)';
|
|
||||||
|
|
||||||
return {
|
|
||||||
async sendTransactionAsync(
|
|
||||||
txData?: Partial<TxData> | undefined,
|
|
||||||
opts: SendTransactionOpts = { shouldValidate: true },
|
|
||||||
): Promise<string> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...txData },
|
|
||||||
this.estimateGasAsync.bind(this),
|
|
||||||
);
|
|
||||||
if (opts.shouldValidate !== false) {
|
|
||||||
await this.callAsync(txDataWithDefaults);
|
|
||||||
}
|
|
||||||
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
awaitTransactionSuccessAsync(
|
|
||||||
txData?: Partial<TxData>,
|
|
||||||
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
|
||||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
|
||||||
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
|
||||||
},
|
|
||||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
|
||||||
data: this.getABIEncodedTransactionData(),
|
|
||||||
...txData,
|
|
||||||
});
|
|
||||||
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
|
|
||||||
BaseContract._assertCallParams(callData, defaultBlock);
|
|
||||||
const rawCallResult = await self._performCallAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...callData },
|
|
||||||
defaultBlock,
|
|
||||||
);
|
|
||||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
|
||||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
|
||||||
return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
|
|
||||||
},
|
|
||||||
getABIEncodedTransactionData(): string {
|
|
||||||
return self._strictEncodeArguments(functionSignature, [
|
|
||||||
token.toLowerCase(),
|
|
||||||
owner.toLowerCase(),
|
|
||||||
to.toLowerCase(),
|
|
||||||
amount,
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Internal version of `transformERC20()`. Only callable from within.
|
* Internal version of `transformERC20()`. Only callable from within.
|
||||||
* @param args A `TransformERC20Args` struct.
|
* @param args A `TransformERC20Args` struct.
|
||||||
@ -5169,55 +5078,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Get the address of the allowance target.
|
|
||||||
*/
|
|
||||||
public getAllowanceTarget(): ContractTxFunctionObj<string> {
|
|
||||||
const self = (this as any) as IZeroExContract;
|
|
||||||
const functionSignature = 'getAllowanceTarget()';
|
|
||||||
|
|
||||||
return {
|
|
||||||
async sendTransactionAsync(
|
|
||||||
txData?: Partial<TxData> | undefined,
|
|
||||||
opts: SendTransactionOpts = { shouldValidate: true },
|
|
||||||
): Promise<string> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...txData },
|
|
||||||
this.estimateGasAsync.bind(this),
|
|
||||||
);
|
|
||||||
if (opts.shouldValidate !== false) {
|
|
||||||
await this.callAsync(txDataWithDefaults);
|
|
||||||
}
|
|
||||||
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
awaitTransactionSuccessAsync(
|
|
||||||
txData?: Partial<TxData>,
|
|
||||||
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
|
||||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
|
||||||
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
|
||||||
},
|
|
||||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
|
||||||
data: this.getABIEncodedTransactionData(),
|
|
||||||
...txData,
|
|
||||||
});
|
|
||||||
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
|
|
||||||
BaseContract._assertCallParams(callData, defaultBlock);
|
|
||||||
const rawCallResult = await self._performCallAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...callData },
|
|
||||||
defaultBlock,
|
|
||||||
);
|
|
||||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
|
||||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
|
||||||
return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
|
|
||||||
},
|
|
||||||
getABIEncodedTransactionData(): string {
|
|
||||||
return self._strictEncodeArguments(functionSignature, []);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Get the canonical hash of a limit order.
|
* Get the canonical hash of a limit order.
|
||||||
* @param order The limit order.
|
* @param order The limit order.
|
||||||
@ -6020,60 +5880,6 @@ export class IZeroExContract extends BaseContract {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Gets the maximum amount of an ERC20 token `token` that can be
|
|
||||||
* pulled from `owner`.
|
|
||||||
* @param token The token to spend.
|
|
||||||
* @param owner The owner of the tokens.
|
|
||||||
*/
|
|
||||||
public getSpendableERC20BalanceOf(token: string, owner: string): ContractTxFunctionObj<BigNumber> {
|
|
||||||
const self = (this as any) as IZeroExContract;
|
|
||||||
assert.isString('token', token);
|
|
||||||
assert.isString('owner', owner);
|
|
||||||
const functionSignature = 'getSpendableERC20BalanceOf(address,address)';
|
|
||||||
|
|
||||||
return {
|
|
||||||
async sendTransactionAsync(
|
|
||||||
txData?: Partial<TxData> | undefined,
|
|
||||||
opts: SendTransactionOpts = { shouldValidate: true },
|
|
||||||
): Promise<string> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...txData },
|
|
||||||
this.estimateGasAsync.bind(this),
|
|
||||||
);
|
|
||||||
if (opts.shouldValidate !== false) {
|
|
||||||
await this.callAsync(txDataWithDefaults);
|
|
||||||
}
|
|
||||||
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
awaitTransactionSuccessAsync(
|
|
||||||
txData?: Partial<TxData>,
|
|
||||||
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
|
||||||
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
|
||||||
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
|
||||||
},
|
|
||||||
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
|
||||||
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
|
||||||
data: this.getABIEncodedTransactionData(),
|
|
||||||
...txData,
|
|
||||||
});
|
|
||||||
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
|
||||||
},
|
|
||||||
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
|
||||||
BaseContract._assertCallParams(callData, defaultBlock);
|
|
||||||
const rawCallResult = await self._performCallAsync(
|
|
||||||
{ data: this.getABIEncodedTransactionData(), ...callData },
|
|
||||||
defaultBlock,
|
|
||||||
);
|
|
||||||
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
|
||||||
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
|
||||||
return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
|
||||||
},
|
|
||||||
getABIEncodedTransactionData(): string {
|
|
||||||
return self._strictEncodeArguments(functionSignature, [token.toLowerCase(), owner.toLowerCase()]);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Return the current wallet instance that will serve as the execution
|
* Return the current wallet instance that will serve as the execution
|
||||||
* context for transformations.
|
* context for transformations.
|
||||||
@ -6536,6 +6342,68 @@ export class IZeroExContract extends BaseContract {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Efficiently sell directly to PancakeSwap/BakerySwap/Sushiswap.
|
||||||
|
* @param tokens Sell path.
|
||||||
|
* @param sellAmount of `tokens[0]` Amount to sell.
|
||||||
|
* @param minBuyAmount Minimum amount of `tokens[-1]` to buy.
|
||||||
|
* @param fork The protocol fork to use.
|
||||||
|
*/
|
||||||
|
public sellToPancakeSwap(
|
||||||
|
tokens: string[],
|
||||||
|
sellAmount: BigNumber,
|
||||||
|
minBuyAmount: BigNumber,
|
||||||
|
fork: number | BigNumber,
|
||||||
|
): ContractTxFunctionObj<BigNumber> {
|
||||||
|
const self = (this as any) as IZeroExContract;
|
||||||
|
assert.isArray('tokens', tokens);
|
||||||
|
assert.isBigNumber('sellAmount', sellAmount);
|
||||||
|
assert.isBigNumber('minBuyAmount', minBuyAmount);
|
||||||
|
assert.isNumberOrBigNumber('fork', fork);
|
||||||
|
const functionSignature = 'sellToPancakeSwap(address[],uint256,uint256,uint8)';
|
||||||
|
|
||||||
|
return {
|
||||||
|
async sendTransactionAsync(
|
||||||
|
txData?: Partial<TxData> | undefined,
|
||||||
|
opts: SendTransactionOpts = { shouldValidate: true },
|
||||||
|
): Promise<string> {
|
||||||
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
|
||||||
|
{ data: this.getABIEncodedTransactionData(), ...txData },
|
||||||
|
this.estimateGasAsync.bind(this),
|
||||||
|
);
|
||||||
|
if (opts.shouldValidate !== false) {
|
||||||
|
await this.callAsync(txDataWithDefaults);
|
||||||
|
}
|
||||||
|
return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
|
||||||
|
},
|
||||||
|
awaitTransactionSuccessAsync(
|
||||||
|
txData?: Partial<TxData>,
|
||||||
|
opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
|
||||||
|
): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
|
||||||
|
return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
|
||||||
|
},
|
||||||
|
async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
|
||||||
|
const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
|
||||||
|
data: this.getABIEncodedTransactionData(),
|
||||||
|
...txData,
|
||||||
|
});
|
||||||
|
return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
|
||||||
|
},
|
||||||
|
async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
|
||||||
|
BaseContract._assertCallParams(callData, defaultBlock);
|
||||||
|
const rawCallResult = await self._performCallAsync(
|
||||||
|
{ data: this.getABIEncodedTransactionData(), ...callData },
|
||||||
|
defaultBlock,
|
||||||
|
);
|
||||||
|
const abiEncoder = self._lookupAbiEncoder(functionSignature);
|
||||||
|
BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder);
|
||||||
|
return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
|
||||||
|
},
|
||||||
|
getABIEncodedTransactionData(): string {
|
||||||
|
return self._strictEncodeArguments(functionSignature, [tokens, sellAmount, minBuyAmount, fork]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Efficiently sell directly to uniswap/sushiswap.
|
* Efficiently sell directly to uniswap/sushiswap.
|
||||||
* @param tokens Sell path.
|
* @param tokens Sell path.
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "8.0.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Remove exchangeProxyAllowanceTarget"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1616005394,
|
"timestamp": 1616005394,
|
||||||
"version": "7.0.1",
|
"version": "7.0.1",
|
||||||
|
@ -315,7 +315,6 @@ export async function runMigrationsAsync(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const exchangeProxy = await fullMigrateExchangeProxyAsync(txDefaults.from, provider, txDefaults);
|
const exchangeProxy = await fullMigrateExchangeProxyAsync(txDefaults.from, provider, txDefaults);
|
||||||
const exchangeProxyAllowanceTargetAddress = await exchangeProxy.getAllowanceTarget().callAsync();
|
|
||||||
const exchangeProxyFlashWalletAddress = await exchangeProxy.getTransformWallet().callAsync();
|
const exchangeProxyFlashWalletAddress = await exchangeProxy.getTransformWallet().callAsync();
|
||||||
|
|
||||||
// Deploy transformers.
|
// Deploy transformers.
|
||||||
@ -382,7 +381,6 @@ export async function runMigrationsAsync(
|
|||||||
dexForwarderBridge: NULL_ADDRESS,
|
dexForwarderBridge: NULL_ADDRESS,
|
||||||
exchangeProxyGovernor: NULL_ADDRESS,
|
exchangeProxyGovernor: NULL_ADDRESS,
|
||||||
exchangeProxy: exchangeProxy.address,
|
exchangeProxy: exchangeProxy.address,
|
||||||
exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress,
|
|
||||||
exchangeProxyTransformerDeployer: txDefaults.from,
|
exchangeProxyTransformerDeployer: txDefaults.from,
|
||||||
exchangeProxyFlashWallet: exchangeProxyFlashWalletAddress,
|
exchangeProxyFlashWallet: exchangeProxyFlashWalletAddress,
|
||||||
exchangeProxyLiquidityProviderSandbox: NULL_ADDRESS,
|
exchangeProxyLiquidityProviderSandbox: NULL_ADDRESS,
|
||||||
|
@ -1,4 +1,13 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "1.4.0",
|
||||||
|
"changes": [
|
||||||
|
{
|
||||||
|
"note": "Added Nerve",
|
||||||
|
"pr": 181
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"timestamp": 1616005394,
|
"timestamp": 1616005394,
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { AbiEncoder, BigNumber, NULL_ADDRESS } from '@0x/utils';
|
import { AbiEncoder, BigNumber, hexUtils, NULL_ADDRESS } from '@0x/utils';
|
||||||
import * as ethjs from 'ethereumjs-util';
|
import * as ethjs from 'ethereumjs-util';
|
||||||
|
|
||||||
import { LimitOrder, LimitOrderFields, RfqOrder, RfqOrderFields } from './orders';
|
import { LimitOrder, LimitOrderFields, RfqOrder, RfqOrderFields } from './orders';
|
||||||
import { Signature, SIGNATURE_ABI } from './signature_utils';
|
import { Signature, SIGNATURE_ABI } from './signature_utils';
|
||||||
|
|
||||||
const BRIDGE_ORDER_ABI_COMPONENTS = [
|
const BRIDGE_ORDER_ABI_COMPONENTS = [
|
||||||
{ name: 'source', type: 'uint256' },
|
{ name: 'source', type: 'bytes32' },
|
||||||
{ name: 'takerTokenAmount', type: 'uint256' },
|
{ name: 'takerTokenAmount', type: 'uint256' },
|
||||||
{ name: 'makerTokenAmount', type: 'uint256' },
|
{ name: 'makerTokenAmount', type: 'uint256' },
|
||||||
{ name: 'bridgeData', type: 'bytes' },
|
{ name: 'bridgeData', type: 'bytes' },
|
||||||
@ -104,38 +104,38 @@ export interface FillQuoteTransformerData {
|
|||||||
refundReceiver: string;
|
refundReceiver: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tslint:disable: enum-naming
|
||||||
/**
|
/**
|
||||||
* Identifies the DEX type of a bridge order.
|
* Identifies the DEX protocol used to fill a bridge order.
|
||||||
*/
|
*/
|
||||||
export enum BridgeSource {
|
export enum BridgeProtocol {
|
||||||
Balancer,
|
Unknown,
|
||||||
Bancor,
|
|
||||||
// tslint:disable-next-line: enum-naming
|
|
||||||
CoFiX,
|
|
||||||
Curve,
|
Curve,
|
||||||
Cream,
|
UniswapV2,
|
||||||
CryptoCom,
|
Uniswap,
|
||||||
Dodo,
|
Balancer,
|
||||||
Kyber,
|
Kyber,
|
||||||
LiquidityProvider,
|
|
||||||
Mooniswap,
|
Mooniswap,
|
||||||
MStable,
|
MStable,
|
||||||
Oasis,
|
Oasis,
|
||||||
Shell,
|
Shell,
|
||||||
Snowswap,
|
Dodo,
|
||||||
Sushiswap,
|
|
||||||
Swerve,
|
|
||||||
Uniswap,
|
|
||||||
UniswapV2,
|
|
||||||
DodoV2,
|
DodoV2,
|
||||||
Linkswap,
|
CryptoCom,
|
||||||
|
Bancor,
|
||||||
|
CoFiX,
|
||||||
|
Nerve,
|
||||||
}
|
}
|
||||||
|
// tslint:enable: enum-naming
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `FillQuoteTransformer.BridgeOrder`
|
* `FillQuoteTransformer.BridgeOrder`
|
||||||
*/
|
*/
|
||||||
export interface FillQuoteTransformerBridgeOrder {
|
export interface FillQuoteTransformerBridgeOrder {
|
||||||
source: BridgeSource;
|
// A bytes32 hex where the upper 16 bytes are an int128, right-aligned
|
||||||
|
// protocol ID and the lower 16 bytes are a bytes16, left-aligned,
|
||||||
|
// ASCII source name.
|
||||||
|
source: string;
|
||||||
takerTokenAmount: BigNumber;
|
takerTokenAmount: BigNumber;
|
||||||
makerTokenAmount: BigNumber;
|
makerTokenAmount: BigNumber;
|
||||||
bridgeData: string;
|
bridgeData: string;
|
||||||
@ -353,3 +353,17 @@ export function encodePositiveSlippageFeeTransformerData(data: PositiveSlippageF
|
|||||||
export function decodePositiveSlippageFeeTransformerData(encoded: string): PositiveSlippageFeeTransformerData {
|
export function decodePositiveSlippageFeeTransformerData(encoded: string): PositiveSlippageFeeTransformerData {
|
||||||
return positiveSlippageFeeTransformerDataEncoder.decode(encoded);
|
return positiveSlippageFeeTransformerDataEncoder.decode(encoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packs a bridge protocol ID and an ASCII DEX name into a single byte32.
|
||||||
|
*/
|
||||||
|
export function encodeBridgeSourceId(protocol: BridgeProtocol, name: string): string {
|
||||||
|
const nameBuf = Buffer.from(name);
|
||||||
|
if (nameBuf.length > 16) {
|
||||||
|
throw new Error(`"${name}" is too long to be a bridge source name (max of 16 ascii chars)`);
|
||||||
|
}
|
||||||
|
return hexUtils.concat(
|
||||||
|
hexUtils.leftPad(hexUtils.toHex(protocol), 16),
|
||||||
|
hexUtils.rightPad(hexUtils.toHex(Buffer.from(name)), 16),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user