chore: [asset swapper] sampler Solidity 0.6 + Bridge addresses in AS (#4)

* Refactor excess interfaces

* Compiles on 0.6

* Refactored into try/catch

* Rebase and Refactored to v06

* Handle invalid registry in LP

* Update packages/asset-swapper/contracts/src/LiquidityProviderSampler.sol

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>

* chore: [asset-swapper] Move Bridge Addresses and Gas schedule

* curve->pool

* lint

* Refactor to fix module load order

* Move FEE Schedule

* rollup: Swerve/Sushi/SnowSwap/DODO (#7)

* rollup: Swerve/Sushi

* DODO Rollup + Snowswap Swerve

* hardcode addresses temporarily

* rebase

* rename to SUSHISWAP_ROUTER

* CHANGELOGs

* CHANGELOGs

Co-authored-by: Lawrence Forman <lawrence@0xproject.com>
This commit is contained in:
Jacob Evans 2020-10-27 15:16:09 +10:00 committed by GitHub
parent 8de0282d92
commit 99f5be8378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 1663 additions and 612 deletions

View File

@ -1,4 +1,13 @@
[
{
"version": "3.6.0",
"changes": [
{
"note": "Add `SwerveBridge` and `SnowSwapBridge` (duplicate of `CurveBridge`)",
"pr": 2707
}
]
},
{
"version": "3.5.0",
"changes": [

View File

@ -0,0 +1,119 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/ICurve.sol";
// solhint-disable not-rely-on-time
// solhint-disable space-after-comma
contract SnowSwapBridge is
IERC20Bridge,
IWallet,
DeploymentConstants
{
struct SnowSwapBridgeData {
address curveAddress;
bytes4 exchangeFunctionSelector;
address fromTokenAddress;
int128 fromCoinIdx;
int128 toCoinIdx;
}
/// @dev Callback for `ICurve`. Tries to buy `amount` of
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
/// (DAI, USDC) to the Curve contract, then transfers the bought
/// tokens to `to`.
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoeded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success)
{
// Decode the bridge data to get the SnowSwap metadata.
SnowSwapBridgeData memory data = abi.decode(bridgeData, (SnowSwapBridgeData));
require(toTokenAddress != data.fromTokenAddress, "SnowSwapBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance.
{
(bool didSucceed, bytes memory resultData) =
data.curveAddress.call(abi.encodeWithSelector(
data.exchangeFunctionSelector,
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount
));
if (!didSucceed) {
assembly { revert(add(resultData, 32), mload(resultData)) }
}
}
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
// Transfer the converted `toToken`s to `to`.
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
emit ERC20BridgeTransfer(
data.fromTokenAddress,
toTokenAddress,
fromTokenBalance,
toTokenBalance,
from,
to
);
return BRIDGE_SUCCESS;
}
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
/// and sign for itself in orders. Always succeeds.
/// @return magicValue Magic success bytes, always.
function isValidSignature(
bytes32,
bytes calldata
)
external
view
returns (bytes4 magicValue)
{
return LEGACY_WALLET_MAGIC_VALUE;
}
}

View File

@ -0,0 +1,119 @@
/*
Copyright 2019 ZeroEx Intl.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/IWallet.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "../interfaces/IERC20Bridge.sol";
import "../interfaces/ICurve.sol";
// solhint-disable not-rely-on-time
// solhint-disable space-after-comma
contract SwerveBridge is
IERC20Bridge,
IWallet,
DeploymentConstants
{
struct SwerveBridgeData {
address curveAddress;
bytes4 exchangeFunctionSelector;
address fromTokenAddress;
int128 fromCoinIdx;
int128 toCoinIdx;
}
/// @dev Callback for `ICurve`. Tries to buy `amount` of
/// `toTokenAddress` tokens by selling the entirety of the opposing asset
/// (DAI, USDC) to the Curve contract, then transfers the bought
/// tokens to `to`.
/// @param toTokenAddress The token to give to `to` (i.e DAI, USDC, USDT).
/// @param from The maker (this contract).
/// @param to The recipient of the bought tokens.
/// @param amount Minimum amount of `toTokenAddress` tokens to buy.
/// @param bridgeData The abi-encoeded "from" token address.
/// @return success The magic bytes if successful.
function bridgeTransferFrom(
address toTokenAddress,
address from,
address to,
uint256 amount,
bytes calldata bridgeData
)
external
returns (bytes4 success)
{
// Decode the bridge data to get the SwerveBridgeData metadata.
SwerveBridgeData memory data = abi.decode(bridgeData, (SwerveBridgeData));
require(toTokenAddress != data.fromTokenAddress, "SwerveBridge/INVALID_PAIR");
uint256 fromTokenBalance = IERC20Token(data.fromTokenAddress).balanceOf(address(this));
// Grant an allowance to the exchange to spend `fromTokenAddress` token.
LibERC20Token.approveIfBelow(data.fromTokenAddress, data.curveAddress, fromTokenBalance);
// Try to sell all of this contract's `fromTokenAddress` token balance.
{
(bool didSucceed, bytes memory resultData) =
data.curveAddress.call(abi.encodeWithSelector(
data.exchangeFunctionSelector,
data.fromCoinIdx,
data.toCoinIdx,
// dx
fromTokenBalance,
// min dy
amount
));
if (!didSucceed) {
assembly { revert(add(resultData, 32), mload(resultData)) }
}
}
uint256 toTokenBalance = IERC20Token(toTokenAddress).balanceOf(address(this));
// Transfer the converted `toToken`s to `to`.
LibERC20Token.transfer(toTokenAddress, to, toTokenBalance);
emit ERC20BridgeTransfer(
data.fromTokenAddress,
toTokenAddress,
fromTokenBalance,
toTokenBalance,
from,
to
);
return BRIDGE_SUCCESS;
}
/// @dev `SignatureType.Wallet` callback, so that this bridge can be the maker
/// and sign for itself in orders. Always succeeds.
/// @return magicValue Magic success bytes, always.
function isValidSignature(
bytes32,
bytes calldata
)
external
view
returns (bytes4 magicValue)
{
return LEGACY_WALLET_MAGIC_VALUE;
}
}

View File

@ -38,7 +38,7 @@
"docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
},
"config": {
"abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CreamBridge|CurveBridge|DODOBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IShell|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|ShellBridge|StaticCallProxy|SushiSwapBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
"abis": "./test/generated-artifacts/@(BalancerBridge|BancorBridge|ChaiBridge|CreamBridge|CurveBridge|DODOBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IBancorNetwork|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IMooniswap|IShell|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MooniswapBridge|MultiAssetProxy|Ownable|ShellBridge|SnowSwapBridge|StaticCallProxy|SushiSwapBridge|SwerveBridge|TestBancorBridge|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
},
"repository": {

View File

@ -47,8 +47,10 @@ import * as MStableBridge from '../generated-artifacts/MStableBridge.json';
import * as MultiAssetProxy from '../generated-artifacts/MultiAssetProxy.json';
import * as Ownable from '../generated-artifacts/Ownable.json';
import * as ShellBridge from '../generated-artifacts/ShellBridge.json';
import * as SnowSwapBridge from '../generated-artifacts/SnowSwapBridge.json';
import * as StaticCallProxy from '../generated-artifacts/StaticCallProxy.json';
import * as SushiSwapBridge from '../generated-artifacts/SushiSwapBridge.json';
import * as SwerveBridge from '../generated-artifacts/SwerveBridge.json';
import * as TestBancorBridge from '../generated-artifacts/TestBancorBridge.json';
import * as TestChaiBridge from '../generated-artifacts/TestChaiBridge.json';
import * as TestDexForwarderBridge from '../generated-artifacts/TestDexForwarderBridge.json';
@ -85,7 +87,9 @@ export const artifacts = {
MixinGasToken: MixinGasToken as ContractArtifact,
MooniswapBridge: MooniswapBridge as ContractArtifact,
ShellBridge: ShellBridge as ContractArtifact,
SnowSwapBridge: SnowSwapBridge as ContractArtifact,
SushiSwapBridge: SushiSwapBridge as ContractArtifact,
SwerveBridge: SwerveBridge as ContractArtifact,
UniswapBridge: UniswapBridge as ContractArtifact,
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,

View File

@ -45,8 +45,10 @@ export * from '../generated-wrappers/mooniswap_bridge';
export * from '../generated-wrappers/multi_asset_proxy';
export * from '../generated-wrappers/ownable';
export * from '../generated-wrappers/shell_bridge';
export * from '../generated-wrappers/snow_swap_bridge';
export * from '../generated-wrappers/static_call_proxy';
export * from '../generated-wrappers/sushi_swap_bridge';
export * from '../generated-wrappers/swerve_bridge';
export * from '../generated-wrappers/test_bancor_bridge';
export * from '../generated-wrappers/test_chai_bridge';
export * from '../generated-wrappers/test_dex_forwarder_bridge';

View File

@ -47,8 +47,10 @@ import * as MStableBridge from '../test/generated-artifacts/MStableBridge.json';
import * as MultiAssetProxy from '../test/generated-artifacts/MultiAssetProxy.json';
import * as Ownable from '../test/generated-artifacts/Ownable.json';
import * as ShellBridge from '../test/generated-artifacts/ShellBridge.json';
import * as SnowSwapBridge from '../test/generated-artifacts/SnowSwapBridge.json';
import * as StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json';
import * as SushiSwapBridge from '../test/generated-artifacts/SushiSwapBridge.json';
import * as SwerveBridge from '../test/generated-artifacts/SwerveBridge.json';
import * as TestBancorBridge from '../test/generated-artifacts/TestBancorBridge.json';
import * as TestChaiBridge from '../test/generated-artifacts/TestChaiBridge.json';
import * as TestDexForwarderBridge from '../test/generated-artifacts/TestDexForwarderBridge.json';
@ -85,7 +87,9 @@ export const artifacts = {
MixinGasToken: MixinGasToken as ContractArtifact,
MooniswapBridge: MooniswapBridge as ContractArtifact,
ShellBridge: ShellBridge as ContractArtifact,
SnowSwapBridge: SnowSwapBridge as ContractArtifact,
SushiSwapBridge: SushiSwapBridge as ContractArtifact,
SwerveBridge: SwerveBridge as ContractArtifact,
UniswapBridge: UniswapBridge as ContractArtifact,
UniswapV2Bridge: UniswapV2Bridge as ContractArtifact,
IAssetData: IAssetData as ContractArtifact,

View File

@ -45,8 +45,10 @@ export * from '../test/generated-wrappers/mooniswap_bridge';
export * from '../test/generated-wrappers/multi_asset_proxy';
export * from '../test/generated-wrappers/ownable';
export * from '../test/generated-wrappers/shell_bridge';
export * from '../test/generated-wrappers/snow_swap_bridge';
export * from '../test/generated-wrappers/static_call_proxy';
export * from '../test/generated-wrappers/sushi_swap_bridge';
export * from '../test/generated-wrappers/swerve_bridge';
export * from '../test/generated-wrappers/test_bancor_bridge';
export * from '../test/generated-wrappers/test_chai_bridge';
export * from '../test/generated-wrappers/test_dex_forwarder_bridge';

View File

@ -45,8 +45,10 @@
"generated-artifacts/MultiAssetProxy.json",
"generated-artifacts/Ownable.json",
"generated-artifacts/ShellBridge.json",
"generated-artifacts/SnowSwapBridge.json",
"generated-artifacts/StaticCallProxy.json",
"generated-artifacts/SushiSwapBridge.json",
"generated-artifacts/SwerveBridge.json",
"generated-artifacts/TestBancorBridge.json",
"generated-artifacts/TestChaiBridge.json",
"generated-artifacts/TestDexForwarderBridge.json",
@ -101,8 +103,10 @@
"test/generated-artifacts/MultiAssetProxy.json",
"test/generated-artifacts/Ownable.json",
"test/generated-artifacts/ShellBridge.json",
"test/generated-artifacts/SnowSwapBridge.json",
"test/generated-artifacts/StaticCallProxy.json",
"test/generated-artifacts/SushiSwapBridge.json",
"test/generated-artifacts/SwerveBridge.json",
"test/generated-artifacts/TestBancorBridge.json",
"test/generated-artifacts/TestChaiBridge.json",
"test/generated-artifacts/TestDexForwarderBridge.json",

View File

@ -1,4 +1,13 @@
[
{
"version": "0.5.0",
"changes": [
{
"note": "Add `Swerve`, `SnowSwap`, `DODO` and `SushiSwap` into FQT",
"pr": 7
}
]
},
{
"version": "0.4.0",
"changes": [

View File

@ -22,11 +22,13 @@ pragma experimental ABIEncoderV2;
import "./mixins/MixinAdapterAddresses.sol";
import "./mixins/MixinBalancer.sol";
import "./mixins/MixinCurve.sol";
import "./mixins/MixinDodo.sol";
import "./mixins/MixinKyber.sol";
import "./mixins/MixinMooniswap.sol";
import "./mixins/MixinMStable.sol";
import "./mixins/MixinOasis.sol";
import "./mixins/MixinShell.sol";
import "./mixins/MixinSushiswap.sol";
import "./mixins/MixinUniswap.sol";
import "./mixins/MixinUniswapV2.sol";
import "./mixins/MixinZeroExBridge.sol";
@ -35,11 +37,13 @@ contract BridgeAdapter is
MixinAdapterAddresses,
MixinBalancer,
MixinCurve,
MixinDodo,
MixinKyber,
MixinMooniswap,
MixinMStable,
MixinOasis,
MixinShell,
MixinSushiswap,
MixinUniswap,
MixinUniswapV2,
MixinZeroExBridge
@ -48,11 +52,15 @@ contract BridgeAdapter is
address private immutable BALANCER_BRIDGE_ADDRESS;
address private immutable CREAM_BRIDGE_ADDRESS;
address private immutable CURVE_BRIDGE_ADDRESS;
address private immutable DODO_BRIDGE_ADDRESS;
address private immutable KYBER_BRIDGE_ADDRESS;
address private immutable MOONISWAP_BRIDGE_ADDRESS;
address private immutable MSTABLE_BRIDGE_ADDRESS;
address private immutable OASIS_BRIDGE_ADDRESS;
address private immutable SHELL_BRIDGE_ADDRESS;
address private immutable SNOW_SWAP_BRIDGE_ADDRESS;
address private immutable SUSHISWAP_BRIDGE_ADDRESS;
address private immutable SWERVE_BRIDGE_ADDRESS;
address private immutable UNISWAP_BRIDGE_ADDRESS;
address private immutable UNISWAP_V2_BRIDGE_ADDRESS;
@ -76,11 +84,13 @@ contract BridgeAdapter is
public
MixinBalancer()
MixinCurve()
MixinDodo(addresses)
MixinKyber(addresses)
MixinMooniswap(addresses)
MixinMStable(addresses)
MixinOasis(addresses)
MixinShell(addresses)
MixinSushiswap(addresses)
MixinUniswap(addresses)
MixinUniswapV2(addresses)
MixinZeroExBridge()
@ -92,9 +102,13 @@ contract BridgeAdapter is
MSTABLE_BRIDGE_ADDRESS = addresses.mStableBridge;
OASIS_BRIDGE_ADDRESS = addresses.oasisBridge;
SHELL_BRIDGE_ADDRESS = addresses.shellBridge;
SUSHISWAP_BRIDGE_ADDRESS = addresses.sushiswapBridge;
SWERVE_BRIDGE_ADDRESS = addresses.swerveBridge;
UNISWAP_BRIDGE_ADDRESS = addresses.uniswapBridge;
UNISWAP_V2_BRIDGE_ADDRESS = addresses.uniswapV2Bridge;
CREAM_BRIDGE_ADDRESS = addresses.creamBridge;
SNOW_SWAP_BRIDGE_ADDRESS = addresses.snowSwapBridge;
DODO_BRIDGE_ADDRESS = addresses.dodoBridge;
}
function trade(
@ -118,12 +132,20 @@ contract BridgeAdapter is
"BridgeAdapter/INVALID_BRIDGE_ADDRESS"
);
if (bridgeAddress == CURVE_BRIDGE_ADDRESS) {
if (bridgeAddress == CURVE_BRIDGE_ADDRESS ||
bridgeAddress == SWERVE_BRIDGE_ADDRESS ||
bridgeAddress == SNOW_SWAP_BRIDGE_ADDRESS) {
boughtAmount = _tradeCurve(
buyToken,
sellAmount,
bridgeData
);
} else if (bridgeAddress == SUSHISWAP_BRIDGE_ADDRESS) {
boughtAmount = _tradeSushiswap(
buyToken,
sellAmount,
bridgeData
);
} else if (bridgeAddress == UNISWAP_V2_BRIDGE_ADDRESS) {
boughtAmount = _tradeUniswapV2(
buyToken,
@ -136,7 +158,8 @@ contract BridgeAdapter is
sellAmount,
bridgeData
);
} else if (bridgeAddress == BALANCER_BRIDGE_ADDRESS || bridgeAddress == CREAM_BRIDGE_ADDRESS) {
} else if (bridgeAddress == BALANCER_BRIDGE_ADDRESS ||
bridgeAddress == CREAM_BRIDGE_ADDRESS) {
boughtAmount = _tradeBalancer(
buyToken,
sellAmount,
@ -172,6 +195,12 @@ contract BridgeAdapter is
sellAmount,
bridgeData
);
} else if (bridgeAddress == DODO_BRIDGE_ADDRESS) {
boughtAmount = _tradeDodo(
buyToken,
sellAmount,
bridgeData
);
} else {
boughtAmount = _tradeZeroExBridge(
bridgeAddress,

View File

@ -26,20 +26,26 @@ contract MixinAdapterAddresses
address balancerBridge;
address creamBridge;
address curveBridge;
address dodoBridge;
address kyberBridge;
address mooniswapBridge;
address mStableBridge;
address oasisBridge;
address shellBridge;
address snowSwapBridge;
address swerveBridge;
address sushiswapBridge;
address uniswapBridge;
address uniswapV2Bridge;
// Exchanges
address kyberNetworkProxy;
address oasis;
address sushiswapRouter;
address uniswapV2Router;
address uniswapExchangeFactory;
address mStable;
address shell;
address dodoHelper;
// Other
address weth;
}

View File

@ -0,0 +1,97 @@
/*
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 "./MixinAdapterAddresses.sol";
interface IDODOHelper {
function querySellQuoteToken(address dodo, uint256 amount) external view returns (uint256);
}
interface IDODO {
function sellBaseToken(uint256 amount, uint256 minReceiveQuote, bytes calldata data) external returns (uint256);
function buyBaseToken(uint256 amount, uint256 maxPayQuote, bytes calldata data) external returns (uint256);
}
contract MixinDodo is
MixinAdapterAddresses
{
using LibERC20TokenV06 for IERC20TokenV06;
/// @dev Mainnet address of the `DOODO Helper` contract.
IDODOHelper private immutable DODO_HELPER;
constructor(AdapterAddresses memory addresses)
public
{
DODO_HELPER = IDODOHelper(addresses.dodoHelper);
}
function _tradeDodo(
IERC20TokenV06 /* buyToken */,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
(address fromTokenAddress,
address pool,
bool isSellBase) = abi.decode(bridgeData, (address, address, bool));
// Grant the Dodo pool contract an allowance to sell the first token.
IERC20TokenV06(fromTokenAddress).approveIfBelow(pool, sellAmount);
if (isSellBase) {
// Sell the Base token directly against the contract
boughtAmount = IDODO(pool).sellBaseToken(
// amount to sell
sellAmount,
// min receive amount
1,
new bytes(0)
);
} else {
// Need to re-calculate the sell quote amount into buyBase
boughtAmount = DODO_HELPER.querySellQuoteToken(
pool,
sellAmount
);
IDODO(pool).buyBaseToken(
// amount to buy
boughtAmount,
// max pay amount
sellAmount,
new bytes(0)
);
}
return boughtAmount;
}
}

View File

@ -69,7 +69,7 @@ contract MixinShell is
sellAmount
);
uint256 buyAmount = SHELL.originSwap(
boughtAmount = SHELL.originSwap(
fromTokenAddress,
address(buyToken),
// Sell all tokens we hold.
@ -79,6 +79,6 @@ contract MixinShell is
// deadline
block.timestamp + 1
);
return buyAmount;
return boughtAmount;
}
}

View File

@ -0,0 +1,79 @@
/*
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 "./MixinAdapterAddresses.sol";
import "./MixinUniswapV2.sol";
contract MixinSushiswap is
MixinAdapterAddresses
{
using LibERC20TokenV06 for IERC20TokenV06;
/// @dev Mainnet address of the `SushiswapRouter` contract.
IUniswapV2Router02 private immutable SUSHISWAP_ROUTER;
constructor(AdapterAddresses memory addresses)
public
{
SUSHISWAP_ROUTER = IUniswapV2Router02(addresses.sushiswapRouter);
}
function _tradeSushiswap(
IERC20TokenV06 buyToken,
uint256 sellAmount,
bytes memory bridgeData
)
internal
returns (uint256 boughtAmount)
{
// solhint-disable indent
address[] memory path = abi.decode(bridgeData, (address[]));
// solhint-enable indent
require(path.length >= 2, "SushiswapBridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO");
require(
path[path.length - 1] == address(buyToken),
"SushiswapBridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"
);
// Grant the Uniswap router an allowance to sell the first token.
IERC20TokenV06(path[0]).approveIfBelow(
address(SUSHISWAP_ROUTER),
sellAmount
);
uint[] memory amounts = SUSHISWAP_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];
}
}

View File

@ -65,11 +65,13 @@ import * as MetaTransactionsFeature from '../test/generated-artifacts/MetaTransa
import * as MixinAdapterAddresses from '../test/generated-artifacts/MixinAdapterAddresses.json';
import * as MixinBalancer from '../test/generated-artifacts/MixinBalancer.json';
import * as MixinCurve from '../test/generated-artifacts/MixinCurve.json';
import * as MixinDodo from '../test/generated-artifacts/MixinDodo.json';
import * as MixinKyber from '../test/generated-artifacts/MixinKyber.json';
import * as MixinMooniswap from '../test/generated-artifacts/MixinMooniswap.json';
import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json';
import * as MixinOasis from '../test/generated-artifacts/MixinOasis.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 MixinUniswapV2 from '../test/generated-artifacts/MixinUniswapV2.json';
import * as MixinZeroExBridge from '../test/generated-artifacts/MixinZeroExBridge.json';
@ -176,11 +178,13 @@ export const artifacts = {
MixinAdapterAddresses: MixinAdapterAddresses as ContractArtifact,
MixinBalancer: MixinBalancer as ContractArtifact,
MixinCurve: MixinCurve as ContractArtifact,
MixinDodo: MixinDodo as ContractArtifact,
MixinKyber: MixinKyber as ContractArtifact,
MixinMStable: MixinMStable as ContractArtifact,
MixinMooniswap: MixinMooniswap as ContractArtifact,
MixinOasis: MixinOasis as ContractArtifact,
MixinShell: MixinShell as ContractArtifact,
MixinSushiswap: MixinSushiswap as ContractArtifact,
MixinUniswap: MixinUniswap as ContractArtifact,
MixinUniswapV2: MixinUniswapV2 as ContractArtifact,
MixinZeroExBridge: MixinZeroExBridge as ContractArtifact,

View File

@ -65,10 +65,13 @@ blockchainTests.resets('FillQuoteTransformer', env => {
mooniswapBridge: NULL_ADDRESS,
mStableBridge: NULL_ADDRESS,
oasisBridge: NULL_ADDRESS,
sushiswapBridge: NULL_ADDRESS,
swerveBridge: NULL_ADDRESS,
uniswapBridge: NULL_ADDRESS,
uniswapV2Bridge: NULL_ADDRESS,
kyberNetworkProxy: NULL_ADDRESS,
oasis: NULL_ADDRESS,
sushiswapRouter: NULL_ADDRESS,
uniswapV2Router: NULL_ADDRESS,
uniswapExchangeFactory: NULL_ADDRESS,
mStable: NULL_ADDRESS,
@ -76,6 +79,9 @@ blockchainTests.resets('FillQuoteTransformer', env => {
shellBridge: NULL_ADDRESS,
shell: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
dodoHelper: NULL_ADDRESS,
snowSwapBridge: NULL_ADDRESS,
},
);
transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync(

View File

@ -63,11 +63,13 @@ export * from '../test/generated-wrappers/meta_transactions_feature';
export * from '../test/generated-wrappers/mixin_adapter_addresses';
export * from '../test/generated-wrappers/mixin_balancer';
export * from '../test/generated-wrappers/mixin_curve';
export * from '../test/generated-wrappers/mixin_dodo';
export * from '../test/generated-wrappers/mixin_kyber';
export * from '../test/generated-wrappers/mixin_m_stable';
export * from '../test/generated-wrappers/mixin_mooniswap';
export * from '../test/generated-wrappers/mixin_oasis';
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_v2';
export * from '../test/generated-wrappers/mixin_zero_ex_bridge';

View File

@ -87,11 +87,13 @@
"test/generated-artifacts/MixinAdapterAddresses.json",
"test/generated-artifacts/MixinBalancer.json",
"test/generated-artifacts/MixinCurve.json",
"test/generated-artifacts/MixinDodo.json",
"test/generated-artifacts/MixinKyber.json",
"test/generated-artifacts/MixinMStable.json",
"test/generated-artifacts/MixinMooniswap.json",
"test/generated-artifacts/MixinOasis.json",
"test/generated-artifacts/MixinShell.json",
"test/generated-artifacts/MixinSushiswap.json",
"test/generated-artifacts/MixinUniswap.json",
"test/generated-artifacts/MixinUniswapV2.json",
"test/generated-artifacts/MixinZeroExBridge.json",

View File

@ -1,4 +1,17 @@
[
{
"version": "4.8.0",
"changes": [
{
"note": "Moved Bridge addresses into Asset-swapper",
"pr": 4
},
{
"note": "Updated Sampler to Solidity 0.6",
"pr": 4
}
]
},
{
"timestamp": 1603487270,
"version": "4.7.1",
@ -172,8 +185,12 @@
"pr": 2731
},
{
"note": "Support DODO Trade Allowed parameter to automatically disable the pool",
"note": "Support `DODO` Trade Allowed parameter to automatically disable the pool",
"pr": 2732
},
{
"note": "Added `SwerveBridge` and `SnowSwapBridge` deployed addresses",
"pr": 7
}
],
"timestamp": 1603265572

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
contract ApproximateBuys {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IBalancer.sol";
@ -78,24 +78,24 @@ contract BalancerSampler {
if (takerTokenAmounts[i] > _bmul(poolState.takerTokenBalance, MAX_IN_RATIO)) {
break;
}
(bool didSucceed, bytes memory resultData) =
poolAddress.staticcall.gas(BALANCER_CALL_GAS)(
abi.encodeWithSelector(
pool.calcOutGivenIn.selector,
try
pool.calcOutGivenIn
{gas: BALANCER_CALL_GAS}
(
poolState.takerTokenBalance,
poolState.takerTokenWeight,
poolState.makerTokenBalance,
poolState.makerTokenWeight,
takerTokenAmounts[i],
poolState.swapFee
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
} else {
)
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -136,24 +136,24 @@ contract BalancerSampler {
if (makerTokenAmounts[i] > _bmul(poolState.makerTokenBalance, MAX_OUT_RATIO)) {
break;
}
(bool didSucceed, bytes memory resultData) =
poolAddress.staticcall.gas(BALANCER_CALL_GAS)(
abi.encodeWithSelector(
pool.calcInGivenOut.selector,
try
pool.calcInGivenOut
{gas: BALANCER_CALL_GAS}
(
poolState.takerTokenBalance,
poolState.takerTokenWeight,
poolState.makerTokenBalance,
poolState.makerTokenWeight,
makerTokenAmounts[i],
poolState.swapFee
));
uint256 sellAmount = 0;
if (didSucceed) {
sellAmount = abi.decode(resultData, (uint256));
} else {
)
returns (uint256 amount)
{
takerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
takerTokenAmounts[i] = sellAmount;
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/ICurve.sol";

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
@ -50,6 +50,8 @@ contract DODOSampler is
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromDODO(
@ -104,6 +106,8 @@ contract DODOSampler is
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample.
/// @return sellBase whether the bridge needs to sell the base token
/// @return pool the DODO pool address
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromDODO(
@ -167,32 +171,34 @@ contract DODOSampler is
(address, address, address)
);
bool didSucceed;
bytes memory resultData;
// We will get called to sell both the taker token and also to sell the maker token
if (takerToken == baseToken) {
// If base token then use the original query on the pool
(didSucceed, resultData) =
pool.staticcall.gas(DODO_CALL_GAS)(
abi.encodeWithSelector(
IDODO(0).querySellBaseToken.selector,
sellAmount
));
try
IDODO(pool).querySellBaseToken
{gas: DODO_CALL_GAS}
(sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
} else {
// If quote token then use helper, this is less accurate
(didSucceed, resultData) =
_getDODOHelperAddress().staticcall.gas(DODO_CALL_GAS)(
abi.encodeWithSelector(
IDODOHelper(0).querySellQuoteToken.selector,
pool,
sellAmount
));
try
IDODOHelper(_getDODOHelperAddress()).querySellQuoteToken
{gas: DODO_CALL_GAS}
(pool, sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
if (!didSucceed) {
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256));
}
}

View File

@ -0,0 +1,340 @@
/*
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;
// // 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;
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./BalancerSampler.sol";

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IEth2Dai.sol";
import "./SamplerUtils.sol";
@ -50,23 +50,17 @@ contract Eth2DaiSampler is
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getEth2DaiAddress().staticcall.gas(ETH2DAI_CALL_GAS)(
abi.encodeWithSelector(
IEth2Dai(0).getBuyAmount.selector,
makerToken,
takerToken,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (buyAmount == 0) {
try
IEth2Dai(_getEth2DaiAddress()).getBuyAmount
{gas: ETH2DAI_CALL_GAS}
(makerToken, takerToken, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -89,23 +83,17 @@ contract Eth2DaiSampler is
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getEth2DaiAddress().staticcall.gas(ETH2DAI_CALL_GAS)(
abi.encodeWithSelector(
IEth2Dai(0).getPayAmount.selector,
takerToken,
makerToken,
makerTokenAmounts[i]
));
uint256 sellAmount = 0;
if (didSucceed) {
sellAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (sellAmount == 0) {
try
IEth2Dai(_getEth2DaiAddress()).getPayAmount
{gas: ETH2DAI_CALL_GAS}
(takerToken, makerToken, makerTokenAmounts[i])
returns (uint256 amount)
{
takerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
takerTokenAmounts[i] = sellAmount;
}
}
}

View File

@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IKyberNetwork.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
@ -109,52 +109,66 @@ contract KyberSampler is
// All other reserves should be ignored with this hint
bytes32[] memory selectedReserves = new bytes32[](1);
selectedReserves[0] = reserveId;
uint256[] memory emptySplits = new uint256[](0);
bool didSucceed;
bytes memory resultData;
if (takerToken == _getWethAddress()) {
// ETH to Token
(didSucceed, resultData) =
address(kyberHint).staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector(
IKyberHintHandler(0).buildEthToTokenHint.selector,
try
kyberHint.buildEthToTokenHint
{gas: KYBER_CALL_GAS}
(
makerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
new uint256[](0)));
emptySplits
)
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
} else if (makerToken == _getWethAddress()) {
// Token to ETH
(didSucceed, resultData) =
address(kyberHint).staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector(
IKyberHintHandler(0).buildTokenToEthHint.selector,
try
kyberHint.buildTokenToEthHint
{gas: KYBER_CALL_GAS}
(
takerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
new uint256[](0)));
emptySplits
)
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
} else {
// Token to Token
// We use the same reserve both ways
(didSucceed, resultData) =
address(kyberHint).staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector(
IKyberHintHandler(0).buildTokenToTokenHint.selector,
try
kyberHint.buildTokenToTokenHint
{gas: KYBER_CALL_GAS}
(
takerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
new uint256[](0),
emptySplits,
makerToken,
IKyberHintHandler.TradeType.MaskIn,
selectedReserves,
new uint256[](0)
emptySplits
)
);
returns (bytes memory result)
{
return result;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
}
}
// If successful decode the hint
if (didSucceed) {
hint = abi.decode(resultData, (bytes));
}
return hint;
}
function _sampleSellForApproximateBuyFromKyber(
@ -164,25 +178,22 @@ contract KyberSampler is
)
private
view
returns (uint256 buyAmount)
returns (uint256)
{
(address makerToken, bytes memory hint) =
abi.decode(makerTokenData, (address, bytes));
(address takerToken, ) =
abi.decode(takerTokenData, (address, bytes));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellFromKyberNetwork.selector,
hint,
takerToken,
makerToken,
sellAmount
));
if (!success) {
try
this.sampleSellFromKyberNetwork
(hint, takerToken, makerToken, sellAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256));
}
function sampleSellFromKyberNetwork(
@ -200,31 +211,30 @@ contract KyberSampler is
return 0;
}
(bool didSucceed, bytes memory resultData) =
_getKyberNetworkProxyAddress().staticcall.gas(KYBER_CALL_GAS)(
abi.encodeWithSelector(
IKyberNetworkProxy(0).getExpectedRateAfterFee.selector,
try
IKyberNetworkProxy(_getKyberNetworkProxyAddress()).getExpectedRateAfterFee
{gas: KYBER_CALL_GAS}
(
takerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : takerToken,
makerToken == _getWethAddress() ? KYBER_ETH_ADDRESS : makerToken,
takerTokenAmount,
0, // fee
hint
));
uint256 rate = 0;
if (didSucceed) {
(rate) = abi.decode(resultData, (uint256));
} else {
)
returns (uint256 rate)
{
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount =
rate *
takerTokenAmount *
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
return makerTokenAmount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
uint256 makerTokenDecimals = _getTokenDecimals(makerToken);
uint256 takerTokenDecimals = _getTokenDecimals(takerToken);
makerTokenAmount =
rate *
takerTokenAmount *
10 ** makerTokenDecimals /
10 ** takerTokenDecimals /
10 ** 18;
return makerTokenAmount;
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "./interfaces/ILiquidityProvider.sol";
import "./interfaces/ILiquidityProviderRegistry.sol";
import "./ApproximateBuys.sol";
@ -66,23 +66,17 @@ contract LiquidityProviderSampler is
}
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
providerAddress.staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
ILiquidityProvider(0).getSellQuote.selector,
takerToken,
makerToken,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (buyAmount == 0) {
try
ILiquidityProvider(providerAddress).getSellQuote
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -136,14 +130,15 @@ contract LiquidityProviderSampler is
if (registryAddress == address(0)) {
return address(0);
}
bytes memory callData = abi.encodeWithSelector(
ILiquidityProviderRegistry(0).getLiquidityProviderForMarket.selector,
ILiquidityProviderRegistry.getLiquidityProviderForMarket.selector,
takerToken,
makerToken
);
(bool didSucceed, bytes memory returnData) = registryAddress.staticcall(callData);
if (didSucceed && returnData.length == 32) {
return LibBytes.readAddress(returnData, 12);
return LibBytesV06.readAddress(returnData, 12);
}
}
@ -160,19 +155,16 @@ contract LiquidityProviderSampler is
abi.decode(takerTokenData, (address, address));
(address makerToken) =
abi.decode(makerTokenData, (address));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromLiquidityProviderRegistry.selector,
plpRegistryAddress,
takerToken,
makerToken,
_toSingleValueArray(sellAmount)
));
if (!success) {
try
this.sampleSellsFromLiquidityProviderRegistry
{gas: DEFAULT_CALL_GAS}
(plpRegistryAddress, takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts, address)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
// solhint-disable-next-line indent
(uint256[] memory amounts, ) = abi.decode(resultData, (uint256[], address));
return amounts[0];
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,11 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IMStable.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
@ -54,23 +53,17 @@ contract MStableSampler is
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
address(_getMUsdAddress()).staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IMStable(0).getSwapOutput.selector,
takerToken,
makerToken,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
(, , buyAmount) = abi.decode(resultData, (bool, string, uint256));
}
// Exit early if the amount is too high for the source to serve
if (buyAmount == 0) {
try
IMStable(_getMUsdAddress()).getSwapOutput
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
returns (bool, string memory, uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -112,17 +105,15 @@ contract MStableSampler is
abi.decode(takerTokenData, (address));
(address makerToken) =
abi.decode(makerTokenData, (address));
(bool success, bytes memory resultData) =
address(this).staticcall(abi.encodeWithSelector(
this.sampleSellsFromMStable.selector,
takerToken,
makerToken,
_toSingleValueArray(sellAmount)
));
if (!success) {
try
this.sampleSellsFromMStable
(takerToken, makerToken, _toSingleValueArray(sellAmount))
returns (uint256[] memory amounts)
{
return amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
// solhint-disable-next-line indent
return abi.decode(resultData, (uint256[]))[0];
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,11 +16,11 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./IMooniswap.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IMooniswap.sol";
import "./ApproximateBuys.sol";
import "./SamplerUtils.sol";
@ -37,6 +37,7 @@ contract MooniswapSampler is
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param takerTokenAmounts Taker token sell amount for each sample.
/// @return pool The contract address for the pool
/// @return makerTokenAmounts Maker amounts bought at each taker token
/// amount.
function sampleSellsFromMooniswap(
@ -80,7 +81,7 @@ contract MooniswapSampler is
)
public
view
returns (uint256 makerTokenAmount)
returns (uint256)
{
// Find the pool for the pair.
IMooniswap pool = IMooniswap(
@ -88,26 +89,26 @@ contract MooniswapSampler is
);
// If there is no pool then return early
if (address(pool) == address(0)) {
return makerTokenAmount;
return 0;
}
uint256 poolBalance = mooniswapTakerToken == address(0)
? address(pool).balance
: IERC20Token(mooniswapTakerToken).balanceOf(address(pool));
: IERC20TokenV06(mooniswapTakerToken).balanceOf(address(pool));
// If the pool balance is smaller than the sell amount
// don't sample to avoid multiplication overflow in buys
if (poolBalance < takerTokenAmount) {
return makerTokenAmount;
return 0;
}
(bool didSucceed, bytes memory resultData) =
address(pool).staticcall.gas(MOONISWAP_CALL_GAS)(
abi.encodeWithSelector(
pool.getReturn.selector,
mooniswapTakerToken,
mooniswapMakerToken,
takerTokenAmount
));
if (didSucceed) {
makerTokenAmount = abi.decode(resultData, (uint256));
try
pool.getReturn
{gas: MOONISWAP_CALL_GAS}
(mooniswapTakerToken, mooniswapMakerToken, takerTokenAmount)
returns (uint256 amount)
{
return amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
return 0;
}
}
@ -115,6 +116,7 @@ contract MooniswapSampler is
/// @param takerToken Address of the taker token (what to sell).
/// @param makerToken Address of the maker token (what to buy).
/// @param makerTokenAmounts Maker token sell amount for each sample.
/// @return pool The contract address for the pool
/// @return takerTokenAmounts Taker amounts sold at each maker token
/// amount.
function sampleBuysFromMooniswap(

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IMultiBridge.sol";

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,21 +16,107 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
interface IExchange {
/// @dev V3 Order structure.
struct Order {
// Address that created the order.
address makerAddress;
// Address that is allowed to fill the order.
// If set to 0, any address is allowed to fill the order.
address takerAddress;
// Address that will recieve fees when order is filled.
address feeRecipientAddress;
// Address that is allowed to call Exchange contract methods that affect this order.
// If set to 0, any address is allowed to call these methods.
address senderAddress;
// Amount of makerAsset being offered by maker. Must be greater than 0.
uint256 makerAssetAmount;
// Amount of takerAsset being bid on by maker. Must be greater than 0.
uint256 takerAssetAmount;
// Fee paid to feeRecipient by maker when order is filled.
uint256 makerFee;
// Fee paid to feeRecipient by taker when order is filled.
uint256 takerFee;
// Timestamp in seconds at which order expires.
uint256 expirationTimeSeconds;
// Arbitrary number to facilitate uniqueness of the order's hash.
uint256 salt;
// Encoded data that can be decoded by a specified proxy contract when transferring makerAsset.
// The leading bytes4 references the id of the asset proxy.
bytes makerAssetData;
// Encoded data that can be decoded by a specified proxy contract when transferring takerAsset.
// The leading bytes4 references the id of the asset proxy.
bytes takerAssetData;
// Encoded data that can be decoded by a specified proxy contract when transferring makerFeeAsset.
// The leading bytes4 references the id of the asset proxy.
bytes makerFeeAssetData;
// Encoded data that can be decoded by a specified proxy contract when transferring takerFeeAsset.
// The leading bytes4 references the id of the asset proxy.
bytes takerFeeAssetData;
}
// A valid order remains fillable until it is expired, fully filled, or cancelled.
// An order's status is unaffected by external factors, like account balances.
enum OrderStatus {
INVALID, // Default value
INVALID_MAKER_ASSET_AMOUNT, // Order does not have a valid maker asset amount
INVALID_TAKER_ASSET_AMOUNT, // Order does not have a valid taker asset amount
FILLABLE, // Order is fillable
EXPIRED, // Order has already expired
FULLY_FILLED, // Order is fully filled
CANCELLED // Order has been cancelled
}
/// @dev Order information returned by `getOrderInfo()`.
struct OrderInfo {
OrderStatus orderStatus; // Status that describes order's validity and fillability.
bytes32 orderHash; // EIP712 typed data hash of the order (see LibOrder.getTypedDataHash).
uint256 orderTakerAssetFilledAmount; // Amount of order that has already been filled.
}
/// @dev Gets information about an order: status, hash, and amount filled.
/// @param order Order to gather information on.
/// @return orderInfo Information about the order and its state.
function getOrderInfo(IExchange.Order calldata order)
external
view
returns (IExchange.OrderInfo memory orderInfo);
/// @dev Verifies that a hash has been signed by the given signer.
/// @param hash Any 32-byte hash.
/// @param signature Proof that the hash has been signed by signer.
/// @return isValid `true` if the signature is valid for the given hash and signer.
function isValidHashSignature(
bytes32 hash,
address signerAddress,
bytes calldata signature
)
external
view
returns (bool isValid);
/// @dev Gets an asset proxy.
/// @param assetProxyId Id of the asset proxy.
/// @return The asset proxy registered to assetProxyId. Returns 0x0 if no proxy is registered.
function getAssetProxy(bytes4 assetProxyId)
external
view
returns (address);
}
contract NativeOrderSampler {
using LibSafeMath for uint256;
using LibBytes for bytes;
using LibSafeMathV06 for uint256;
using LibBytesV06 for bytes;
/// @dev The Exchange ERC20Proxy ID.
bytes4 private constant ERC20_ASSET_PROXY_ID = 0xf47261b0;
@ -45,8 +131,8 @@ contract NativeOrderSampler {
view
returns (uint256, uint256)
{
uint256 fromTokenDecimals = LibERC20Token.decimals(makerTokenAddress);
uint256 toTokenDecimals = LibERC20Token.decimals(takerTokenAddress);
uint256 fromTokenDecimals = LibERC20TokenV06.compatDecimals(IERC20TokenV06(makerTokenAddress));
uint256 toTokenDecimals = LibERC20TokenV06.compatDecimals(IERC20TokenV06(takerTokenAddress));
return (fromTokenDecimals, toTokenDecimals);
}
@ -59,7 +145,7 @@ contract NativeOrderSampler {
/// @return orderFillableTakerAssetAmounts How much taker asset can be filled
/// by each order in `orders`.
function getOrderFillableTakerAssetAmounts(
LibOrder.Order[] memory orders,
IExchange.Order[] memory orders,
bytes[] memory orderSignatures,
IExchange exchange
)
@ -69,21 +155,21 @@ contract NativeOrderSampler {
{
orderFillableTakerAssetAmounts = new uint256[](orders.length);
for (uint256 i = 0; i != orders.length; i++) {
// solhint-disable indent
(bool didSucceed, bytes memory resultData) =
address(this)
.staticcall
.gas(DEFAULT_CALL_GAS)
(abi.encodeWithSelector(
this.getOrderFillableTakerAmount.selector,
try
this.getOrderFillableTakerAmount
{gas: DEFAULT_CALL_GAS}
(
orders[i],
orderSignatures[i],
exchange
));
// solhint-enable indent
orderFillableTakerAssetAmounts[i] = didSucceed
? abi.decode(resultData, (uint256))
: 0;
)
returns (uint256 amount)
{
orderFillableTakerAssetAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
orderFillableTakerAssetAmounts[i] = 0;
}
}
}
@ -95,7 +181,7 @@ contract NativeOrderSampler {
/// @return orderFillableMakerAssetAmounts How much maker asset can be filled
/// by each order in `orders`.
function getOrderFillableMakerAssetAmounts(
LibOrder.Order[] memory orders,
IExchange.Order[] memory orders,
bytes[] memory orderSignatures,
IExchange exchange
)
@ -112,7 +198,7 @@ contract NativeOrderSampler {
// convert them to maker asset amounts.
for (uint256 i = 0; i < orders.length; ++i) {
if (orderFillableMakerAssetAmounts[i] != 0) {
orderFillableMakerAssetAmounts[i] = LibMath.getPartialAmountCeil(
orderFillableMakerAssetAmounts[i] = LibMathV06.getPartialAmountCeil(
orderFillableMakerAssetAmounts[i],
orders[i].takerAssetAmount,
orders[i].makerAssetAmount
@ -124,10 +210,11 @@ contract NativeOrderSampler {
/// @dev Get the fillable taker amount of an order, taking into account
/// order state, maker fees, and maker balances.
function getOrderFillableTakerAmount(
LibOrder.Order memory order,
IExchange.Order memory order,
bytes memory signature,
IExchange exchange
)
virtual
public
view
returns (uint256 fillableTakerAmount)
@ -139,27 +226,27 @@ contract NativeOrderSampler {
return 0;
}
LibOrder.OrderInfo memory orderInfo = exchange.getOrderInfo(order);
if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE) {
IExchange.OrderInfo memory orderInfo = exchange.getOrderInfo(order);
if (orderInfo.orderStatus != IExchange.OrderStatus.FILLABLE) {
return 0;
}
if (!exchange.isValidHashSignature(orderInfo.orderHash, order.makerAddress, signature)) {
return 0;
}
address spender = exchange.getAssetProxy(ERC20_ASSET_PROXY_ID);
IERC20Token makerToken = _getTokenFromERC20AssetData(order.makerAssetData);
if (makerToken == IERC20Token(0)) {
IERC20TokenV06 makerToken = _getTokenFromERC20AssetData(order.makerAssetData);
if (makerToken == IERC20TokenV06(0)) {
return 0;
}
IERC20Token makerFeeToken = order.makerFee > 0
IERC20TokenV06 makerFeeToken = order.makerFee > 0
? _getTokenFromERC20AssetData(order.makerFeeAssetData)
: IERC20Token(0);
: IERC20TokenV06(0);
uint256 remainingTakerAmount = order.takerAssetAmount
.safeSub(orderInfo.orderTakerAssetFilledAmount);
fillableTakerAmount = remainingTakerAmount;
// The total fillable maker amount is the remaining fillable maker amount
// PLUS maker fees, if maker fees are denominated in the maker token.
uint256 totalFillableMakerAmount = LibMath.safeGetPartialAmountFloor(
uint256 totalFillableMakerAmount = LibMathV06.safeGetPartialAmountFloor(
remainingTakerAmount,
order.takerAssetAmount,
makerFeeToken == makerToken
@ -168,14 +255,14 @@ contract NativeOrderSampler {
);
// The spendable amount of maker tokens (by the maker) is the lesser of
// the maker's balance and the allowance they've granted to the ERC20Proxy.
uint256 spendableMakerAmount = LibSafeMath.min256(
uint256 spendableMakerAmount = LibSafeMathV06.min256(
makerToken.balanceOf(order.makerAddress),
makerToken.allowance(order.makerAddress, spender)
);
// Scale the fillable taker amount by the ratio of the maker's
// spendable maker amount over the total fillable maker amount.
if (spendableMakerAmount < totalFillableMakerAmount) {
fillableTakerAmount = LibMath.getPartialAmountCeil(
fillableTakerAmount = LibMathV06.getPartialAmountCeil(
spendableMakerAmount,
totalFillableMakerAmount,
remainingTakerAmount
@ -183,15 +270,15 @@ contract NativeOrderSampler {
}
// If the maker fee is denominated in another token, constrain
// the fillable taker amount by how much the maker can pay of that token.
if (makerFeeToken != makerToken && makerFeeToken != IERC20Token(0)) {
uint256 spendableExtraMakerFeeAmount = LibSafeMath.min256(
if (makerFeeToken != makerToken && makerFeeToken != IERC20TokenV06(0)) {
uint256 spendableExtraMakerFeeAmount = LibSafeMathV06.min256(
makerFeeToken.balanceOf(order.makerAddress),
makerFeeToken.allowance(order.makerAddress, spender)
);
if (spendableExtraMakerFeeAmount < order.makerFee) {
fillableTakerAmount = LibSafeMath.min256(
fillableTakerAmount = LibSafeMathV06.min256(
fillableTakerAmount,
LibMath.getPartialAmountCeil(
LibMathV06.getPartialAmountCeil(
spendableExtraMakerFeeAmount,
order.makerFee,
remainingTakerAmount
@ -204,16 +291,16 @@ contract NativeOrderSampler {
function _getTokenFromERC20AssetData(bytes memory assetData)
private
pure
returns (IERC20Token token)
returns (IERC20TokenV06 token)
{
if (assetData.length == 0) {
return IERC20Token(address(0));
return IERC20TokenV06(address(0));
}
if (assetData.length != 36 ||
assetData.readBytes4(0) != ERC20_ASSET_PROXY_ID)
{
return IERC20Token(address(0));
return IERC20TokenV06(address(0));
}
return IERC20Token(assetData.readAddress(16));
return IERC20TokenV06(assetData.readAddress(16));
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
contract SamplerUtils {
@ -28,11 +28,12 @@ contract SamplerUtils {
/// @param tokenAddress Address of the token.
/// @return decimals The decimal places for the token.
function _getTokenDecimals(address tokenAddress)
virtual
internal
view
returns (uint8 decimals)
{
return LibERC20Token.decimals(tokenAddress);
return LibERC20TokenV06.compatDecimals(IERC20TokenV06(tokenAddress));
}
function _toSingleValueArray(uint256 v)

View File

@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IShell.sol";
contract ShellSampler is
@ -48,23 +48,17 @@ contract ShellSampler is
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
address(_getShellAddress()).staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IShell(0).viewOriginSwap.selector,
takerToken,
makerToken,
takerTokenAmounts[i]
));
uint256 buyAmount = 0;
if (didSucceed) {
buyAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (buyAmount == 0) {
try
IShell(_getShellAddress()).viewOriginSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, takerTokenAmounts[i])
returns (uint256 amount)
{
makerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -88,23 +82,17 @@ contract ShellSampler is
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
address(_getShellAddress()).staticcall.gas(DEFAULT_CALL_GAS)(
abi.encodeWithSelector(
IShell(0).viewTargetSwap.selector,
takerToken,
makerToken,
makerTokenAmounts[i]
));
uint256 sellAmount = 0;
if (didSucceed) {
sellAmount = abi.decode(resultData, (uint256));
}
// Exit early if the amount is too high for the source to serve
if (sellAmount == 0) {
try
IShell(_getShellAddress()).viewTargetSwap
{gas: DEFAULT_CALL_GAS}
(takerToken, makerToken, makerTokenAmounts[i])
returns (uint256 amount)
{
takerTokenAmounts[i] = amount;
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
takerTokenAmounts[i] = sellAmount;
}
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IUniswapV2Router01.sol";
@ -47,21 +47,17 @@ contract SushiSwapSampler is
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
router.staticcall.gas(SUSHISWAP_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsOut.selector,
takerTokenAmounts[i],
path
));
uint256 buyAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
buyAmount = abi.decode(resultData, (uint256[]))[path.length - 1];
} else {
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;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -83,21 +79,17 @@ contract SushiSwapSampler is
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
router.staticcall.gas(SUSHISWAP_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsIn.selector,
makerTokenAmounts[i],
path
));
uint256 sellAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
sellAmount = abi.decode(resultData, (uint256[]))[0];
} else {
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;
}
takerTokenAmounts[i] = sellAmount;
}
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,14 +16,14 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
contract TwoHopSampler {
using LibBytes for bytes;
using LibBytesV06 for bytes;
struct HopInfo {
uint256 sourceIndex;

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,19 +16,25 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol";
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IUniswapExchangeQuotes.sol";
import "./SamplerUtils.sol";
interface IUniswapExchangeFactory {
/// @dev Get the exchange for a token.
/// @param tokenAddress The address of the token contract.
function getExchange(address tokenAddress)
external
view
returns (address);
}
contract UniswapSampler is
DeploymentConstants,
SamplerUtils

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,10 +16,10 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol";
import "./DeploymentConstants.sol";
import "./interfaces/IUniswapV2Router01.sol";
@ -45,21 +45,17 @@ contract UniswapV2Sampler is
uint256 numSamples = takerTokenAmounts.length;
makerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsOut.selector,
takerTokenAmounts[i],
path
));
uint256 buyAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
buyAmount = abi.decode(resultData, (uint256[]))[path.length - 1];
} else {
try
IUniswapV2Router01(_getUniswapV2Router01Address()).getAmountsOut
{gas: UNISWAPV2_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;
}
makerTokenAmounts[i] = buyAmount;
}
}
@ -79,21 +75,17 @@ contract UniswapV2Sampler is
uint256 numSamples = makerTokenAmounts.length;
takerTokenAmounts = new uint256[](numSamples);
for (uint256 i = 0; i < numSamples; i++) {
(bool didSucceed, bytes memory resultData) =
_getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)(
abi.encodeWithSelector(
IUniswapV2Router01(0).getAmountsIn.selector,
makerTokenAmounts[i],
path
));
uint256 sellAmount = 0;
if (didSucceed) {
// solhint-disable-next-line indent
sellAmount = abi.decode(resultData, (uint256[]))[0];
} else {
try
IUniswapV2Router01(_getUniswapV2Router01Address()).getAmountsIn
{gas: UNISWAPV2_CALL_GAS}
(makerTokenAmounts[i], path)
returns (uint256[] memory amounts)
{
takerTokenAmounts[i] = amounts[0];
} catch (bytes memory) {
// Swallow failures, leaving all results as zero.
break;
}
takerTokenAmounts[i] = sellAmount;
}
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IBalancer {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
// solhint-disable func-name-mixedcase

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IEth2Dai {

View File

@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
// Keepin everything together
interface IKyberNetwork {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface ILiquidityProvider {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface ILiquidityProviderRegistry {
@ -25,7 +25,7 @@ interface ILiquidityProviderRegistry {
/// (takerToken, makerToken), reverting if the pool does not exist.
/// @param takerToken Taker asset managed by liquidity provider.
/// @param makerToken Maker asset managed by liquidity provider.
/// @return Address of the liquidity provider.
/// @return providerAddress Address of the liquidity provider.
function getLiquidityProviderForMarket(
address takerToken,
address makerToken

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IMStable {

View File

@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IMooniswapRegistry {

View File

@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IMultiBridge {

View File

@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IShell {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IUniswapExchangeQuotes {

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -16,7 +16,7 @@
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
interface IUniswapV2Router01 {

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
@ -35,4 +35,4 @@ contract DummyLiquidityProvider
{
takerTokenAmount = buyAmount + 1;
}
}
}

View File

@ -1,4 +1,4 @@
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
@ -26,7 +26,7 @@ contract DummyLiquidityProviderRegistry
/// @dev Returns the address of pool for a market given market (xAsset, yAsset), or reverts if pool does not exist.
/// @param xToken First asset managed by pool.
/// @param yToken Second asset managed by pool.
/// @return Address of pool.
/// @return poolAddress Address of pool.
function getLiquidityProviderForMarket(
address xToken,
address yToken
@ -41,4 +41,4 @@ contract DummyLiquidityProviderRegistry
"Registry/MARKET_PAIR_NOT_SET"
);
}
}
}

View File

@ -1,6 +1,6 @@
/*
Copyright 2019 ZeroEx Intl.
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.
@ -15,12 +15,9 @@
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-asset-proxy/contracts/src/interfaces/IUniswapExchangeFactory.sol";
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../src/ERC20BridgeSampler.sol";
import "../src/interfaces/IEth2Dai.sol";
import "../src/interfaces/IKyberNetwork.sol";
@ -128,6 +125,7 @@ contract TestERC20BridgeSamplerUniswapExchange is
function getEthToTokenInputPrice(
uint256 ethSold
)
override
external
view
returns (uint256 tokensBought)
@ -145,6 +143,7 @@ contract TestERC20BridgeSamplerUniswapExchange is
function getEthToTokenOutputPrice(
uint256 tokensBought
)
override
external
view
returns (uint256 ethSold)
@ -162,6 +161,7 @@ contract TestERC20BridgeSamplerUniswapExchange is
function getTokenToEthInputPrice(
uint256 tokensSold
)
override
external
view
returns (uint256 ethBought)
@ -179,6 +179,7 @@ contract TestERC20BridgeSamplerUniswapExchange is
function getTokenToEthOutputPrice(
uint256 ethBought
)
override
external
view
returns (uint256 tokensSold)
@ -203,6 +204,7 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
// Deterministic `IUniswapV2Router01.getAmountsOut()`.
function getAmountsOut(uint256 amountIn, address[] calldata path)
override
external
view
returns (uint256[] memory amounts)
@ -223,6 +225,7 @@ contract TestERC20BridgeSamplerUniswapV2Router01 is
// Deterministic `IUniswapV2Router01.getAmountsInt()`.
function getAmountsIn(uint256 amountOut, address[] calldata path)
override
external
view
returns (uint256[] memory amounts)
@ -333,6 +336,7 @@ contract TestERC20BridgeSamplerKyberNetwork is
}
function _getKyberNetworkProxyAddress()
override
internal
view
returns (address)
@ -341,6 +345,7 @@ contract TestERC20BridgeSamplerKyberNetwork is
}
function _getKyberHintHandlerAddress()
override
internal
view
returns (address)
@ -362,6 +367,7 @@ contract TestERC20BridgeSamplerEth2Dai is
address payToken,
uint256 payAmount
)
override
external
view
returns (uint256 buyAmount)
@ -381,6 +387,7 @@ contract TestERC20BridgeSamplerEth2Dai is
address buyToken,
uint256 buyAmount
)
override
external
view
returns (uint256 payAmount)
@ -414,6 +421,7 @@ contract TestERC20BridgeSamplerUniswapExchangeFactory is
// `IUniswapExchangeFactory.getExchange()`.
function getExchange(address tokenAddress)
override
external
view
returns (address)
@ -432,7 +440,7 @@ contract TestERC20BridgeSampler is
TestERC20BridgeSamplerEth2Dai public eth2Dai;
TestERC20BridgeSamplerKyberNetwork public kyber;
uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;
uint8 private constant MAX_ORDER_STATUS = uint8(IExchange.OrderStatus.CANCELLED) + 1;
constructor() public ERC20BridgeSampler() {
uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory();
@ -450,10 +458,11 @@ contract TestERC20BridgeSampler is
// Overridden to return deterministic states.
function getOrderFillableTakerAmount(
LibOrder.Order memory order,
IExchange.Order memory order,
bytes memory,
IExchange
)
override
public
view
returns (uint256 fillableTakerAmount)
@ -463,6 +472,7 @@ contract TestERC20BridgeSampler is
// Overriden to return deterministic decimals.
function _getTokenDecimals(address tokenAddress)
override
internal
view
returns (uint8 decimals)
@ -472,6 +482,7 @@ contract TestERC20BridgeSampler is
// Overriden to point to a custom contract.
function _getEth2DaiAddress()
override
internal
view
returns (address eth2daiAddress)
@ -481,6 +492,7 @@ contract TestERC20BridgeSampler is
// Overriden to point to a custom contract.
function _getUniswapExchangeFactoryAddress()
override
internal
view
returns (address uniswapAddress)
@ -490,6 +502,7 @@ contract TestERC20BridgeSampler is
// Overriden to point to a custom contract.
function _getUniswapV2Router01Address()
override
internal
view
returns (address uniswapV2RouterAddress)
@ -499,6 +512,7 @@ contract TestERC20BridgeSampler is
// Overriden to point to a custom contract.
function _getKyberNetworkProxyAddress()
override
internal
view
returns (address kyberAddress)
@ -508,6 +522,7 @@ contract TestERC20BridgeSampler is
// Overriden to point to a custom contract.
function _getKyberHintHandlerAddress()
override
internal
view
returns (address kyberAddress)

View File

@ -15,11 +15,9 @@
limitations under the License.
*/
pragma solidity ^0.5.9;
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol";
import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol";
import "../src/NativeOrderSampler.sol";
@ -43,7 +41,7 @@ contract TestNativeOrderSamplerToken {
contract TestNativeOrderSampler is
NativeOrderSampler
{
uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1;
uint8 private constant MAX_ORDER_STATUS = uint8(IExchange.OrderStatus.CANCELLED) + 1;
bytes32 private constant VALID_SIGNATURE_HASH = keccak256(hex"01");
function createTokens(uint256 count)
@ -78,17 +76,17 @@ contract TestNativeOrderSampler is
}
// IExchange.getOrderInfo()
function getOrderInfo(LibOrder.Order calldata order)
function getOrderInfo(IExchange.Order calldata order)
external
pure
returns (LibOrder.OrderInfo memory orderInfo)
returns (IExchange.OrderInfo memory orderInfo)
{
// The order salt determines everything.
orderInfo.orderHash = keccak256(abi.encode(order.salt));
if (uint8(order.salt) == 0xFF) {
orderInfo.orderStatus = LibOrder.OrderStatus.FULLY_FILLED;
orderInfo.orderStatus = IExchange.OrderStatus.FULLY_FILLED;
} else {
orderInfo.orderStatus = LibOrder.OrderStatus.FILLABLE;
orderInfo.orderStatus = IExchange.OrderStatus.FILLABLE;
}
// The expiration time is the filled taker asset amount.
orderInfo.orderTakerAssetFilledAmount = order.expirationTimeSeconds;

View File

@ -38,7 +38,7 @@
"config": {
"publicInterfaceContracts": "ERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider",
"abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalancerSampler|CurveSampler|DODOSampler|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|ILiquidityProvider|ILiquidityProviderRegistry|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
"abis": "./test/generated-artifacts/@(ApproximateBuys|BalancerSampler|CurveSampler|DODOSampler|DeploymentConstants|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|IBalancer|ICurve|IEth2Dai|IKyberNetwork|ILiquidityProvider|ILiquidityProviderRegistry|IMStable|IMooniswap|IMultiBridge|IShell|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MooniswapSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|ShellSampler|SushiSwapSampler|TestERC20BridgeSampler|TestNativeOrderSampler|TwoHopSampler|UniswapSampler|UniswapV2Sampler).json",
"postpublish": {
"assets": []
}

View File

@ -1,3 +1,4 @@
import { ChainId } from '@0x/contract-addresses';
import { BigNumber, logUtils } from '@0x/utils';
import {
@ -42,7 +43,7 @@ const PROTOCOL_FEE_MULTIPLIER = new BigNumber(70000);
const MARKET_UTILS_AMOUNT_BUFFER_PERCENTAGE = 0.5;
const DEFAULT_SWAP_QUOTER_OPTS: SwapQuoterOpts = {
chainId: MAINNET_CHAIN_ID,
chainId: ChainId.Mainnet,
orderRefreshIntervalMs: 10000, // 10 seconds
...DEFAULT_ORDER_PRUNER_OPTS,
samplerGasLimit: 250e6,
@ -95,6 +96,21 @@ export const DEFAULT_INFO_LOGGER: LogFunction = (obj, msg) =>
export const DEFAULT_WARNING_LOGGER: LogFunction = (obj, msg) =>
logUtils.warn(`${msg ? `${msg}: ` : ''}${JSON.stringify(obj)}`);
// This feature flag allows us to merge the price-aware RFQ pricing
// project while still controlling when to activate the feature. We plan to do some
// data analysis work and address some of the issues with maker fillable amounts
// in later milestones. Once the feature is fully rolled out and is providing value
// and we have assessed that there is no user impact, we will proceed in cleaning up
// the feature flag. When that time comes, follow this PR to "undo" the feature flag:
// https://github.com/0xProject/0x-monorepo/pull/2735
export const IS_PRICE_AWARE_RFQ_ENABLED: boolean = false;
export {
BRIDGE_ADDRESSES_BY_CHAIN,
DEFAULT_FEE_SCHEDULE,
DEFAULT_GAS_SCHEDULE,
} from './utils/market_operation_utils/constants';
export const constants = {
ETH_GAS_STATION_API_URL,
PROTOCOL_FEE_MULTIPLIER,
@ -122,12 +138,3 @@ export const constants = {
DEFAULT_INFO_LOGGER,
DEFAULT_WARNING_LOGGER,
};
// This feature flag allows us to merge the price-aware RFQ pricing
// project while still controlling when to activate the feature. We plan to do some
// data analysis work and address some of the issues with maker fillable amounts
// in later milestones. Once the feature is fully rolled out and is providing value
// and we have assessed that there is no user impact, we will proceed in cleaning up
// the feature flag. When that time comes, follow this PR to "undo" the feature flag:
// https://github.com/0xProject/0x-monorepo/pull/2735
export const IS_PRICE_AWARE_RFQ_ENABLED: boolean = false;

View File

@ -88,6 +88,7 @@ export { getSwapMinBuyAmount } from './quote_consumers/utils';
export { SwapQuoter } from './swap_quoter';
export {
AffiliateFee,
AssetSwapperContractAddresses,
CalldataInfo,
ExchangeProxyContractOpts,
ExchangeProxyRefundReceiver,
@ -119,7 +120,11 @@ export {
SwapQuoterRfqtOpts,
} from './types';
export { affiliateFeeUtils } from './utils/affiliate_fee_utils';
export { SOURCE_FLAGS } from './utils/market_operation_utils/constants';
export {
BRIDGE_ADDRESSES_BY_CHAIN,
DEFAULT_GAS_SCHEDULE,
SOURCE_FLAGS,
} from './utils/market_operation_utils/constants';
export {
Parameters,
SamplerContractCall,
@ -150,13 +155,13 @@ export {
NativeCollapsedFill,
NativeFillData,
OptimizedMarketOrder,
SnowSwapFillData,
SnowSwapInfo,
SourceInfo,
SourceQuoteOperation,
SushiSwapFillData,
SwerveFillData,
SwerveInfo,
SnowSwapFillData,
SnowSwapInfo,
TokenAdjacencyGraph,
UniswapV2FillData,
} from './utils/market_operation_utils/types';

View File

@ -1,4 +1,4 @@
import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { DevUtilsContract } from '@0x/contract-wrappers';
import { schemas } from '@0x/json-schemas';
import { assetDataUtils, SignedOrder } from '@0x/order-utils';
@ -8,8 +8,9 @@ import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-t
import * as _ from 'lodash';
import { artifacts } from './artifacts';
import { constants, IS_PRICE_AWARE_RFQ_ENABLED } from './constants';
import { BRIDGE_ADDRESSES_BY_CHAIN, constants, IS_PRICE_AWARE_RFQ_ENABLED } from './constants';
import {
AssetSwapperContractAddresses,
CalculateSwapQuoteOpts,
LiquidityForTakerMakerAssetDataPair,
MarketBuySwapQuote,
@ -48,7 +49,7 @@ export class SwapQuoter {
public readonly expiryBufferMs: number;
public readonly chainId: number;
public readonly permittedOrderFeeTypes: Set<OrderPrunerPermittedFeeTypes>;
private readonly _contractAddresses: ContractAddresses;
private readonly _contractAddresses: AssetSwapperContractAddresses;
private readonly _protocolFeeUtils: ProtocolFeeUtils;
private readonly _swapQuoteCalculator: SwapQuoteCalculator;
private readonly _devUtilsContract: DevUtilsContract;
@ -178,7 +179,10 @@ export class SwapQuoter {
this.permittedOrderFeeTypes = permittedOrderFeeTypes;
this._rfqtOptions = rfqt;
this._contractAddresses = options.contractAddresses || getContractAddressesForChainOrThrow(chainId);
this._contractAddresses = options.contractAddresses || {
...getContractAddressesForChainOrThrow(chainId),
...BRIDGE_ADDRESSES_BY_CHAIN[chainId],
};
this._devUtilsContract = new DevUtilsContract(this._contractAddresses.devUtils, provider);
this._protocolFeeUtils = ProtocolFeeUtils.getInstance(
constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS,

View File

@ -1,3 +1,4 @@
import { ChainId } from '@0x/contract-addresses';
import { BlockParam, ContractAddresses, GethCallOverrides } from '@0x/contract-wrappers';
import { TakerRequestQueryParams } from '@0x/quote-server';
import { SignedOrder } from '@0x/types';
@ -282,6 +283,8 @@ export interface SwapQuoterRfqtOpts {
infoLogger?: LogFunction;
}
export type AssetSwapperContractAddresses = ContractAddresses & BridgeContractAddresses;
/**
* chainId: The ethereum chain id. Defaults to 1 (mainnet).
* orderRefreshIntervalMs: The interval in ms that getBuyQuoteAsync should trigger an refresh of orders and order states. Defaults to 10000ms (10s).
@ -290,11 +293,11 @@ export interface SwapQuoterRfqtOpts {
* samplerGasLimit: The gas limit used when querying the sampler contract. Defaults to 36e6
*/
export interface SwapQuoterOpts extends OrderPrunerOpts {
chainId: number;
chainId: ChainId;
orderRefreshIntervalMs: number;
expiryBufferMs: number;
ethereumRpcUrl?: string;
contractAddresses?: ContractAddresses;
contractAddresses?: AssetSwapperContractAddresses;
samplerGasLimit?: number;
liquidityProviderRegistryAddress?: string;
multiBridgeAddress?: string;
@ -380,3 +383,24 @@ export interface SamplerOverrides {
}
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
/**
* The Contract addresses of the deployed Bridges
*/
export interface BridgeContractAddresses {
uniswapBridge: string;
uniswapV2Bridge: string;
eth2DaiBridge: string;
kyberBridge: string;
curveBridge: string;
multiBridge: string;
balancerBridge: string;
bancorBridge: string;
mStableBridge: string;
mooniswapBridge: string;
sushiswapBridge: string;
shellBridge: string;
dodoBridge: string;
creamBridge: string;
swerveBridge: string;
snowswapBridge: string;
}

View File

@ -1,33 +1,51 @@
import { ChainId } from '@0x/contract-addresses';
import { BigNumber } from '@0x/utils';
import { BridgeContractAddresses } from '../../types';
import { SourceFilters } from './source_filters';
import { CurveFunctionSelectors, CurveInfo, ERC20BridgeSource, GetMarketOrdersOpts } from './types';
import {
CurveFillData,
CurveFunctionSelectors,
CurveInfo,
DODOFillData,
ERC20BridgeSource,
FeeSchedule,
FillData,
GetMarketOrdersOpts,
MultiHopFillData,
SushiSwapFillData,
UniswapV2FillData,
} from './types';
// tslint:disable: custom-no-magic-numbers no-bitwise
/**
* Valid sources for market sell.
*/
export const SELL_SOURCE_FILTER = new SourceFilters([
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.UniswapV2,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Curve,
ERC20BridgeSource.Balancer,
// Bancor is sampled off-chain, but this list should only include on-chain sources (used in ERC20BridgeSampler)
// ERC20BridgeSource.Bancor,
ERC20BridgeSource.MStable,
ERC20BridgeSource.Mooniswap,
ERC20BridgeSource.Swerve,
ERC20BridgeSource.SnowSwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Shell,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Dodo,
ERC20BridgeSource.Cream,
]);
export const SELL_SOURCE_FILTER = new SourceFilters(
[
ERC20BridgeSource.Native,
ERC20BridgeSource.Uniswap,
ERC20BridgeSource.UniswapV2,
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Curve,
ERC20BridgeSource.Balancer,
// Bancor is sampled off-chain, but this list should only include on-chain sources (used in ERC20BridgeSampler)
// ERC20BridgeSource.Bancor,
ERC20BridgeSource.MStable,
ERC20BridgeSource.Mooniswap,
ERC20BridgeSource.Swerve,
ERC20BridgeSource.SnowSwap,
ERC20BridgeSource.SushiSwap,
ERC20BridgeSource.Shell,
ERC20BridgeSource.MultiHop,
ERC20BridgeSource.Dodo,
ERC20BridgeSource.Cream,
],
[ERC20BridgeSource.MultiBridge],
);
/**
* Valid sources for market buy.
@ -55,22 +73,10 @@ export const BUY_SOURCE_FILTER = new SourceFilters(
[ERC20BridgeSource.MultiBridge],
);
export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
// tslint:disable-next-line: custom-no-magic-numbers
runLimit: 2 ** 15,
excludedSources: [],
excludedFeeSources: [],
includedSources: [],
bridgeSlippage: 0.005,
maxFallbackSlippage: 0.05,
numSamples: 13,
sampleDistributionBase: 1.05,
feeSchedule: {},
gasSchedule: {},
exchangeProxyOverhead: () => ZERO_AMOUNT,
allowFallback: true,
shouldGenerateQuoteReport: false,
};
/**
* 0x Protocol Fee Multiplier
*/
export const PROTOCOL_FEE_MULTIPLIER = new BigNumber(70000);
/**
* Sources to poll for ETH fee price estimates.
@ -283,3 +289,154 @@ export const ONE_SECOND_MS = 1000;
export const NULL_BYTES = '0x';
export const NULL_ADDRESS = '0x0000000000000000000000000000000000000000';
export const COMPARISON_PRICE_DECIMALS = 5;
const EMPTY_BRIDGE_ADDRESSES: BridgeContractAddresses = {
uniswapBridge: NULL_ADDRESS,
uniswapV2Bridge: NULL_ADDRESS,
eth2DaiBridge: NULL_ADDRESS,
kyberBridge: NULL_ADDRESS,
curveBridge: NULL_ADDRESS,
multiBridge: NULL_ADDRESS,
balancerBridge: NULL_ADDRESS,
bancorBridge: NULL_ADDRESS,
mStableBridge: NULL_ADDRESS,
mooniswapBridge: NULL_ADDRESS,
sushiswapBridge: NULL_ADDRESS,
shellBridge: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
snowswapBridge: NULL_ADDRESS,
swerveBridge: NULL_ADDRESS,
};
export const BRIDGE_ADDRESSES_BY_CHAIN: { [chainId in ChainId]: BridgeContractAddresses } = {
[ChainId.Mainnet]: {
uniswapBridge: '0x36691c4f426eb8f42f150ebde43069a31cb080ad',
uniswapV2Bridge: '0xdcd6011f4c6b80e470d9487f5871a0cba7c93f48',
kyberBridge: '0xadd97271402590564ddd8ad23cb5317b1fb0fffb',
eth2DaiBridge: '0x991c745401d5b5e469b8c3e2cb02c748f08754f1',
curveBridge: '0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09',
multiBridge: '0xc03117a8c9bde203f70aa911cb64a7a0df5ba1e1',
balancerBridge: '0xfe01821ca163844203220cd08e4f2b2fb43ae4e4',
bancorBridge: '0x259897d9699553edbdf8538599242354e957fb94',
mStableBridge: '0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3',
mooniswapBridge: '0x02b7eca484ad960fca3f7709e0b2ac81eec3069c',
sushiswapBridge: '0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5',
shellBridge: '0x21fb3862eed7911e0f8219a077247b849846728d',
dodoBridge: '0xe9da66965a9344aab2167e6813c03f043cc7a6ca',
creamBridge: '0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25',
swerveBridge: '0xf9786d5eb1de47fa56a8f7bb387653c6d410bfee',
snowswapBridge: '0xb1dbe83d15236ec10fdb214c6b89774b454754fd',
},
[ChainId.Kovan]: {
...EMPTY_BRIDGE_ADDRESSES,
uniswapBridge: '0x0e85f89f29998df65402391478e5924700c0079d',
uniswapV2Bridge: '0x7b3530a635d099de0534dc27e46cd7c57578c3c8',
eth2DaiBridge: '0x2d47147429b474d2e4f83e658015858a1312ed5b',
kyberBridge: '0xaecfa25920f892b6eb496e1f6e84037f59da7f44',
curveBridge: '0x81c0ab53a7352d2e97f682a37cba44e54647eefb',
balancerBridge: '0x407b4128e9ecad8769b2332312a9f655cb9f5f3a',
},
[ChainId.Rinkeby]: EMPTY_BRIDGE_ADDRESSES,
[ChainId.Ropsten]: EMPTY_BRIDGE_ADDRESSES,
[ChainId.Ganache]: EMPTY_BRIDGE_ADDRESSES,
};
// tslint:disable:custom-no-magic-numbers
export const DEFAULT_GAS_SCHEDULE: FeeSchedule = {
[ERC20BridgeSource.Native]: () => 150e3,
[ERC20BridgeSource.Uniswap]: () => 90e3,
[ERC20BridgeSource.LiquidityProvider]: () => 140e3,
[ERC20BridgeSource.Eth2Dai]: () => 400e3,
[ERC20BridgeSource.Kyber]: () => 500e3,
[ERC20BridgeSource.Curve]: fillData => {
const poolAddress = (fillData as CurveFillData).pool.poolAddress.toLowerCase();
switch (poolAddress) {
case '0xa5407eae9ba41422680e2e00537571bcc53efbfd':
case '0x93054188d876f558f4a66b2ef1d97d16edf0895b':
case '0x7fc77b5c7614e1533320ea6ddc2eb61fa00a9714':
case '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7':
return 150e3;
case '0xa2b47e3d5c44877cca798226b7b8118f9bfb7a56':
return 750e3;
case '0x45f783cce6b7ff23b2ab2d70e416cdb7d6055f51':
return 850e3;
case '0x79a8c46dea5ada233abaffd40f3a0a2b1e5a4f27':
return 1e6;
case '0x52ea46506b9cc5ef470c5bf89f17dc28bb35d85c':
return 600e3;
default:
throw new Error(`Unrecognized Curve address: ${poolAddress}`);
}
},
[ERC20BridgeSource.MultiBridge]: () => 350e3,
[ERC20BridgeSource.UniswapV2]: (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.SushiSwap]: (fillData?: FillData) => {
// TODO: Different base cost if to/from ETH.
let gas = 95e3;
const path = (fillData as SushiSwapFillData).tokenAddressPath;
if (path.length > 2) {
gas += (path.length - 2) * 60e3; // +60k for each hop.
}
return gas;
},
[ERC20BridgeSource.Balancer]: () => 120e3,
[ERC20BridgeSource.Cream]: () => 300e3,
[ERC20BridgeSource.MStable]: () => 700e3,
[ERC20BridgeSource.Mooniswap]: () => 220e3,
[ERC20BridgeSource.Swerve]: () => 150e3,
[ERC20BridgeSource.Shell]: () => 300e3,
[ERC20BridgeSource.MultiHop]: (fillData?: FillData) => {
const firstHop = (fillData as MultiHopFillData).firstHopSource;
const secondHop = (fillData as MultiHopFillData).secondHopSource;
const firstHopGas = DEFAULT_GAS_SCHEDULE[firstHop.source]!(firstHop.fillData);
const secondHopGas = DEFAULT_GAS_SCHEDULE[secondHop.source]!(secondHop.fillData);
return new BigNumber(firstHopGas)
.plus(secondHopGas)
.plus(30e3)
.toNumber();
},
[ERC20BridgeSource.Dodo]: (fillData?: FillData) => {
const isSellBase = (fillData as DODOFillData).isSellBase;
// Sell base is cheaper as it is natively supported
// sell quote requires additional calculation and overhead
return isSellBase ? 440e3 : 540e3;
},
};
export const DEFAULT_FEE_SCHEDULE: FeeSchedule = Object.assign(
{},
...(Object.keys(DEFAULT_GAS_SCHEDULE) as ERC20BridgeSource[]).map(k => ({
[k]:
k === ERC20BridgeSource.Native
? (fillData: FillData) => PROTOCOL_FEE_MULTIPLIER.plus(DEFAULT_GAS_SCHEDULE[k]!(fillData))
: (fillData: FillData) => DEFAULT_GAS_SCHEDULE[k]!(fillData),
})),
);
// tslint:enable:custom-no-magic-numbers
export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = {
// tslint:disable-next-line: custom-no-magic-numbers
runLimit: 2 ** 15,
excludedSources: [],
excludedFeeSources: [],
includedSources: [],
bridgeSlippage: 0.005,
maxFallbackSlippage: 0.05,
numSamples: 13,
sampleDistributionBase: 1.05,
feeSchedule: DEFAULT_FEE_SCHEDULE,
gasSchedule: DEFAULT_GAS_SCHEDULE,
exchangeProxyOverhead: () => ZERO_AMOUNT,
allowFallback: true,
shouldGenerateQuoteReport: false,
};

View File

@ -1,12 +1,11 @@
import { ContractAddresses } from '@0x/contract-addresses';
import { Web3Wrapper } from '@0x/dev-utils';
import { RFQTIndicativeQuote } from '@0x/quote-server';
import { SignedOrder } from '@0x/types';
import { BigNumber, NULL_ADDRESS } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
import { IS_PRICE_AWARE_RFQ_ENABLED } from '../../constants';
import { MarketOperation, Omit } from '../../types';
import { AssetSwapperContractAddresses, MarketOperation, Omit } from '../../types';
import { QuoteRequestor } from '../quote_requestor';
import { generateQuoteReport, QuoteReport } from './../quote_report_generator';
@ -106,7 +105,7 @@ export class MarketOperationUtils {
constructor(
private readonly _sampler: DexOrderSampler,
private readonly contractAddresses: ContractAddresses,
private readonly contractAddresses: AssetSwapperContractAddresses,
private readonly _orderDomain: OrderDomain,
private readonly _liquidityProviderRegistry: string = NULL_ADDRESS,
private readonly _tokenAdjacencyGraph: TokenAdjacencyGraph = {},

View File

@ -1,10 +1,9 @@
import { ContractAddresses } from '@0x/contract-addresses';
import { assetDataUtils, ERC20AssetData, generatePseudoRandomSalt, orderCalculationUtils } from '@0x/order-utils';
import { RFQTIndicativeQuote } from '@0x/quote-server';
import { SignedOrder } from '@0x/types';
import { AbiEncoder, BigNumber } from '@0x/utils';
import { MarketOperation, SignedOrderWithFillableAmounts } from '../../types';
import { AssetSwapperContractAddresses, MarketOperation, SignedOrderWithFillableAmounts } from '../../types';
import {
ERC20_PROXY_ID,
@ -135,7 +134,7 @@ export interface CreateOrderFromPathOpts {
inputToken: string;
outputToken: string;
orderDomain: OrderDomain;
contractAddresses: ContractAddresses;
contractAddresses: AssetSwapperContractAddresses;
bridgeSlippage: number;
}
@ -182,9 +181,9 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath
case ERC20BridgeSource.Curve:
return opts.contractAddresses.curveBridge;
case ERC20BridgeSource.Swerve:
return opts.contractAddresses.curveBridge;
return opts.contractAddresses.swerveBridge;
case ERC20BridgeSource.SnowSwap:
return opts.contractAddresses.curveBridge;
return opts.contractAddresses.snowswapBridge;
case ERC20BridgeSource.Bancor:
return opts.contractAddresses.bancorBridge;
case ERC20BridgeSource.Balancer:

View File

@ -1,6 +1,6 @@
import { SupportedProvider } from '@0x/dev-utils';
import { SignedOrder } from '@0x/types';
import { BigNumber } from '@0x/utils';
import { BigNumber, NULL_ADDRESS } from '@0x/utils';
import * as _ from 'lodash';
import { ERC20BridgeSamplerContract } from '../../wrappers';
@ -1054,7 +1054,7 @@ export class SamplerOperations {
const _sources = BATCH_SOURCE_FILTERS.exclude(
liquidityProviderRegistryAddress ? [] : [ERC20BridgeSource.LiquidityProvider],
)
.exclude(multiBridgeAddress ? [] : [ERC20BridgeSource.MultiBridge])
.exclude(multiBridgeAddress || multiBridgeAddress === NULL_ADDRESS ? [] : [ERC20BridgeSource.MultiBridge])
.getAllowed(sources);
return _.flatten(
_sources.map(

View File

@ -8,6 +8,7 @@ import { ContractArtifact } from 'ethereum-types';
import * as ApproximateBuys from '../test/generated-artifacts/ApproximateBuys.json';
import * as BalancerSampler from '../test/generated-artifacts/BalancerSampler.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 DummyLiquidityProvider from '../test/generated-artifacts/DummyLiquidityProvider.json';
import * as DummyLiquidityProviderRegistry from '../test/generated-artifacts/DummyLiquidityProviderRegistry.json';
@ -44,9 +45,9 @@ export const artifacts = {
BalancerSampler: BalancerSampler as ContractArtifact,
CurveSampler: CurveSampler as ContractArtifact,
DODOSampler: DODOSampler as ContractArtifact,
DeploymentConstants: DeploymentConstants as ContractArtifact,
ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact,
Eth2DaiSampler: Eth2DaiSampler as ContractArtifact,
IMooniswap: IMooniswap as ContractArtifact,
KyberSampler: KyberSampler as ContractArtifact,
LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact,
MStableSampler: MStableSampler as ContractArtifact,
@ -66,6 +67,7 @@ export const artifacts = {
ILiquidityProvider: ILiquidityProvider as ContractArtifact,
ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact,
IMStable: IMStable as ContractArtifact,
IMooniswap: IMooniswap as ContractArtifact,
IMultiBridge: IMultiBridge as ContractArtifact,
IShell: IShell as ContractArtifact,
IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact,

View File

@ -1,5 +1,5 @@
// tslint:disable: no-unbound-method
import { getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import { ChainId, getContractAddressesForChainOrThrow } from '@0x/contract-addresses';
import {
assertRoughlyEquals,
constants,
@ -9,10 +9,10 @@ import {
Numberish,
randomAddress,
} from '@0x/contracts-test-utils';
import { Web3Wrapper } from '@0x/dev-utils';
import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils';
import { AssetProxyId, ERC20BridgeAssetData, SignedOrder } from '@0x/types';
import { BigNumber, fromTokenUnitAmount, hexUtils, NULL_ADDRESS } from '@0x/utils';
import { Web3Wrapper } from '@0x/web3-wrapper';
import * as _ from 'lodash';
import * as TypeMoq from 'typemoq';
@ -21,6 +21,7 @@ import { IS_PRICE_AWARE_RFQ_ENABLED } from '../src/constants';
import { getRfqtIndicativeQuotesAsync, MarketOperationUtils } from '../src/utils/market_operation_utils/';
import { BalancerPoolsCache } from '../src/utils/market_operation_utils/balancer_utils';
import {
BRIDGE_ADDRESSES_BY_CHAIN,
BUY_SOURCE_FILTER,
POSITIVE_INF,
SELL_SOURCE_FILTER,
@ -38,6 +39,7 @@ import {
ERC20BridgeSource,
FillData,
GenerateOptimizedOrdersOpts,
GetMarketOrdersOpts,
MarketSideLiquidity,
NativeFillData,
} from '../src/utils/market_operation_utils/types';
@ -66,8 +68,12 @@ const SELL_SOURCES = SELL_SOURCE_FILTER.sources;
// tslint:disable: custom-no-magic-numbers promise-function-async
describe('MarketOperationUtils tests', () => {
const CHAIN_ID = 1;
const contractAddresses = { ...getContractAddressesForChainOrThrow(CHAIN_ID), multiBridge: NULL_ADDRESS };
const CHAIN_ID = ChainId.Mainnet;
const contractAddresses = {
...getContractAddressesForChainOrThrow(CHAIN_ID),
multiBridge: NULL_ADDRESS,
...BRIDGE_ADDRESSES_BY_CHAIN[CHAIN_ID],
};
function getMockedQuoteRequestor(
type: 'indicative' | 'firm',
@ -522,13 +528,15 @@ describe('MarketOperationUtils tests', () => {
FILL_AMOUNT,
_.times(NUM_SAMPLES, i => DEFAULT_RATES[ERC20BridgeSource.Native][i]),
);
const DEFAULT_OPTS = {
const DEFAULT_OPTS: Partial<GetMarketOrdersOpts> = {
numSamples: NUM_SAMPLES,
sampleDistributionBase: 1,
bridgeSlippage: 0,
maxFallbackSlippage: 100,
excludedSources: DEFAULT_EXCLUDED,
allowFallback: false,
gasSchedule: {},
feeSchedule: {},
};
beforeEach(() => {
@ -1428,7 +1436,7 @@ describe('MarketOperationUtils tests', () => {
...DEFAULT_OPTS,
numSamples: 4,
excludedSources: [
...DEFAULT_OPTS.excludedSources,
...(DEFAULT_OPTS.excludedSources as ERC20BridgeSource[]),
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
ERC20BridgeSource.Bancor,
@ -1449,13 +1457,15 @@ describe('MarketOperationUtils tests', () => {
FILL_AMOUNT,
_.times(NUM_SAMPLES, () => DEFAULT_RATES[ERC20BridgeSource.Native][0]),
);
const DEFAULT_OPTS = {
const DEFAULT_OPTS: Partial<GetMarketOrdersOpts> = {
numSamples: NUM_SAMPLES,
sampleDistributionBase: 1,
bridgeSlippage: 0,
maxFallbackSlippage: 100,
excludedSources: DEFAULT_EXCLUDED,
allowFallback: false,
gasSchedule: {},
feeSchedule: {},
};
beforeEach(() => {
@ -1869,7 +1879,7 @@ describe('MarketOperationUtils tests', () => {
...DEFAULT_OPTS,
numSamples: 4,
excludedSources: [
...DEFAULT_OPTS.excludedSources,
...(DEFAULT_OPTS.excludedSources as ERC20BridgeSource[]),
ERC20BridgeSource.Eth2Dai,
ERC20BridgeSource.Kyber,
],

View File

@ -1,4 +1,4 @@
import { ContractFunctionObj } from '@0x/base-contract';
import { ContractTxFunctionObj } from '@0x/base-contract';
import { constants } from '@0x/contracts-test-utils';
import { Order } from '@0x/types';
import { BigNumber, hexUtils } from '@0x/utils';
@ -82,7 +82,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
this._handlers = handlers;
}
public batchCall(callDatas: string[]): ContractFunctionObj<string[]> {
public batchCall(callDatas: string[]): ContractTxFunctionObj<string[]> {
return {
...super.batchCall(callDatas),
callAsync: async (..._callArgs: any[]) => callDatas.map(callData => this._callEncodedFunction(callData)),
@ -92,7 +92,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
public getOrderFillableMakerAssetAmounts(
orders: Order[],
signatures: string[],
): ContractFunctionObj<GetOrderFillableAssetAmountResult> {
): ContractTxFunctionObj<GetOrderFillableAssetAmountResult> {
return this._wrapCall(
super.getOrderFillableMakerAssetAmounts,
this._handlers.getOrderFillableMakerAssetAmounts,
@ -105,7 +105,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
public getOrderFillableTakerAssetAmounts(
orders: Order[],
signatures: string[],
): ContractFunctionObj<GetOrderFillableAssetAmountResult> {
): ContractTxFunctionObj<GetOrderFillableAssetAmountResult> {
return this._wrapCall(
super.getOrderFillableTakerAssetAmounts,
this._handlers.getOrderFillableTakerAssetAmounts,
@ -120,7 +120,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
takerAssetAmounts: BigNumber[],
): ContractFunctionObj<[string, BigNumber[]]> {
): ContractTxFunctionObj<[string, BigNumber[]]> {
return this._wrapCall(
super.sampleSellsFromKyberNetwork,
this._handlers.sampleSellsFromKyberNetwork,
@ -135,7 +135,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
takerAssetAmounts: BigNumber[],
): ContractFunctionObj<BigNumber[]> {
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleSellsFromEth2Dai,
this._handlers.sampleSellsFromEth2Dai,
@ -149,7 +149,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
takerAssetAmounts: BigNumber[],
): ContractFunctionObj<BigNumber[]> {
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleSellsFromUniswap,
this._handlers.sampleSellsFromUniswap,
@ -159,7 +159,10 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
);
}
public sampleSellsFromUniswapV2(path: string[], takerAssetAmounts: BigNumber[]): ContractFunctionObj<BigNumber[]> {
public sampleSellsFromUniswapV2(
path: string[],
takerAssetAmounts: BigNumber[],
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleSellsFromUniswapV2,
this._handlers.sampleSellsFromUniswapV2,
@ -173,7 +176,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
takerAssetAmounts: BigNumber[],
): ContractFunctionObj<[BigNumber[], string]> {
): ContractTxFunctionObj<[BigNumber[], string]> {
return this._wrapCall(
super.sampleSellsFromLiquidityProviderRegistry,
this._handlers.sampleSellsFromLiquidityProviderRegistry,
@ -190,7 +193,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
intermediateToken: string,
makerToken: string,
takerAssetAmounts: BigNumber[],
): ContractFunctionObj<BigNumber[]> {
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleSellsFromMultiBridge,
this._handlers.sampleSellsFromMultiBridge,
@ -206,7 +209,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
makerAssetAmounts: BigNumber[],
): ContractFunctionObj<BigNumber[]> {
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleBuysFromEth2Dai,
this._handlers.sampleBuysFromEth2Dai,
@ -220,7 +223,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
takerToken: string,
makerToken: string,
makerAssetAmounts: BigNumber[],
): ContractFunctionObj<BigNumber[]> {
): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleBuysFromUniswap,
this._handlers.sampleBuysFromUniswap,
@ -230,7 +233,7 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
);
}
public sampleBuysFromUniswapV2(path: string[], makerAssetAmounts: BigNumber[]): ContractFunctionObj<BigNumber[]> {
public sampleBuysFromUniswapV2(path: string[], makerAssetAmounts: BigNumber[]): ContractTxFunctionObj<BigNumber[]> {
return this._wrapCall(
super.sampleBuysFromUniswapV2,
this._handlers.sampleBuysFromUniswapV2,
@ -266,11 +269,11 @@ export class MockSamplerContract extends ERC20BridgeSamplerContract {
}
private _wrapCall<TArgs extends any[], TResult>(
superFn: (this: MockSamplerContract, ...args: TArgs) => ContractFunctionObj<TResult>,
superFn: (this: MockSamplerContract, ...args: TArgs) => ContractTxFunctionObj<TResult>,
handler?: (this: MockSamplerContract, ...args: TArgs) => TResult,
// tslint:disable-next-line: trailing-comma
...args: TArgs
): ContractFunctionObj<TResult> {
): ContractTxFunctionObj<TResult> {
return {
...superFn.call(this, ...args),
callAsync: async (..._callArgs: any[]): Promise<TResult> => {

View File

@ -7,6 +7,7 @@ export * from '../test/generated-wrappers/approximate_buys';
export * from '../test/generated-wrappers/balancer_sampler';
export * from '../test/generated-wrappers/curve_sampler';
export * from '../test/generated-wrappers/d_o_d_o_sampler';
export * from '../test/generated-wrappers/deployment_constants';
export * from '../test/generated-wrappers/dummy_liquidity_provider';
export * from '../test/generated-wrappers/dummy_liquidity_provider_registry';
export * from '../test/generated-wrappers/erc20_bridge_sampler';

View File

@ -12,6 +12,7 @@
"test/generated-artifacts/BalancerSampler.json",
"test/generated-artifacts/CurveSampler.json",
"test/generated-artifacts/DODOSampler.json",
"test/generated-artifacts/DeploymentConstants.json",
"test/generated-artifacts/DummyLiquidityProvider.json",
"test/generated-artifacts/DummyLiquidityProviderRegistry.json",
"test/generated-artifacts/ERC20BridgeSampler.json",

View File

@ -1,4 +1,13 @@
[
{
"version": "5.0.0",
"changes": [
{
"note": "Moved Bridge addresses into Asset-swapper",
"pr": 4
}
]
},
{
"version": "4.12.0",
"changes": [

View File

@ -19,33 +19,19 @@
"stakingProxy": "0xa26e80e7dea86279c6d778d702cc413e6cffa777",
"devUtils": "0x74134cf88b21383713e096a5ecf59e297dc7f547",
"erc20BridgeProxy": "0x8ed95d1746bf1e4dab58d8ed4724f1ef95b20db0",
"uniswapBridge": "0x36691c4f426eb8f42f150ebde43069a31cb080ad",
"uniswapV2Bridge": "0xdcd6011f4c6b80e470d9487f5871a0cba7c93f48",
"erc20BridgeSampler": "0xd8c38704c9937ea3312de29f824b4ad3450a5e61",
"kyberBridge": "0xadd97271402590564ddd8ad23cb5317b1fb0fffb",
"eth2DaiBridge": "0x991c745401d5b5e469b8c3e2cb02c748f08754f1",
"chaiBridge": "0x77c31eba23043b9a72d13470f3a3a311344d7438",
"dydxBridge": "0x92af95e37afddac412e5688a9dcc1dd815d4ae53",
"godsUnchainedValidator": "0x09a379ef7218bcfd8913faa8b281ebc5a2e0bc04",
"broker": "0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0",
"chainlinkStopLimit": "0xeb27220f95f364e1d9531992c48613f231839f53",
"curveBridge": "0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09",
"maximumGasPrice": "0xe2bfd35306495d11e3c9db0d8de390cda24563cf",
"dexForwarderBridge": "0xc47b7094f378e54347e281aab170e8cca69d880a",
"multiBridge": "0xc03117a8c9bde203f70aa911cb64a7a0df5ba1e1",
"balancerBridge": "0xfe01821ca163844203220cd08e4f2b2fb43ae4e4",
"bancorBridge": "0x259897d9699553edbdf8538599242354e957fb94",
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
"exchangeProxyTransformerDeployer": "0x39dce47a67ad34344eab877eae3ef1fa2a1d50bb",
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
"mStableBridge": "0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3",
"mooniswapBridge": "0x02b7eca484ad960fca3f7709e0b2ac81eec3069c",
"sushiswapBridge": "0x47ed0262a0b688dcb836d254c6a2e96b6c48a9f5",
"shellBridge": "0x21fb3862eed7911e0f8219a077247b849846728d",
"dodoBridge": "0xe9da66965a9344aab2167e6813c03f043cc7a6ca",
"creamBridge": "0xb9d4bf2c8dab828f4ffb656acdb6c2b497d44f25",
"transformers": {
"wethTransformer": "0x68c0bb685099dc7cb5c5ce2b26185945b357383e",
"payTakerTransformer": "0x49b9df2c58491764cf40cb052dd4243df63622c7",
@ -73,33 +59,19 @@
"staking": "0x4af649ffde640ceb34b1afaba3e0bb8e9698cb01",
"stakingProxy": "0x6acab4c9c4e3a0c78435fdb5ad1719c95460a668",
"erc20BridgeProxy": "0xb344afed348de15eb4a9e180205a2b0739628339",
"uniswapBridge": "0x0000000000000000000000000000000000000000",
"uniswapV2Bridge": "0x0000000000000000000000000000000000000000",
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
"kyberBridge": "0x0000000000000000000000000000000000000000",
"chaiBridge": "0x0000000000000000000000000000000000000000",
"dydxBridge": "0x0000000000000000000000000000000000000000",
"godsUnchainedValidator": "0xd4690a51044db77d91d7aa8f7a3a5ad5da331af0",
"broker": "0x4022e3982f326455f0905de3dbc4449999baf2dc",
"chainlinkStopLimit": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
"curveBridge": "0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09",
"maximumGasPrice": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
"dexForwarderBridge": "0x3261ea1411a1a840aed708896f779e1b837c917e",
"multiBridge": "0x0000000000000000000000000000000000000000",
"balancerBridge": "0x47697b44bd89051e93b4d5857ba8e024800a74ac",
"bancorBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
"mStableBridge": "0x0000000000000000000000000000000000000000",
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
"shellBridge": "0x0000000000000000000000000000000000000000",
"dodoBridge": "0x0000000000000000000000000000000000000000",
"creamBridge": "0x0000000000000000000000000000000000000000",
"transformers": {
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
@ -127,33 +99,19 @@
"staking": "0x6acab4c9c4e3a0c78435fdb5ad1719c95460a668",
"stakingProxy": "0x781ee6683595f823208be6540a279f940e6af196",
"erc20BridgeProxy": "0xa2aa4befed748fba27a3be7dfd2c4b2c6db1f49b",
"uniswapBridge": "0x0000000000000000000000000000000000000000",
"uniswapV2Bridge": "0x0000000000000000000000000000000000000000",
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
"kyberBridge": "0x0000000000000000000000000000000000000000",
"chaiBridge": "0x0000000000000000000000000000000000000000",
"dydxBridge": "0x0000000000000000000000000000000000000000",
"godsUnchainedValidator": "0x0000000000000000000000000000000000000000",
"broker": "0x0dd2d6cabbd8ae7d2fe6840fa597a44b1a7e4747",
"chainlinkStopLimit": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
"curveBridge": "0x1796cd592d19e3bcd744fbb025bb61a6d8cb2c09",
"maximumGasPrice": "0x47697b44bd89051e93b4d5857ba8e024800a74ac",
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
"multiBridge": "0x0000000000000000000000000000000000000000",
"balancerBridge": "0x5d8c9ba74607d2cbc4176882a42d4ace891c1c00",
"bancorBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
"exchangeProxyTransformerDeployer": "0x1c9a27658dd303a31205a3b245e8993b92d4d502",
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
"mStableBridge": "0x0000000000000000000000000000000000000000",
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
"shellBridge": "0x0000000000000000000000000000000000000000",
"dodoBridge": "0x0000000000000000000000000000000000000000",
"creamBridge": "0x0000000000000000000000000000000000000000",
"transformers": {
"wethTransformer": "0x8d822fe2b42f60531203e288f5f357fa79474437",
"payTakerTransformer": "0x150652244723102faeaefa4c79597d097ffa26c6",
@ -181,33 +139,19 @@
"staking": "0x73ea24041e03a012c51a45c307e0ba376af0238c",
"stakingProxy": "0xe94cb304b3f515be7c95fedcfa249a84995fd748",
"erc20BridgeProxy": "0x3577552c1fb7a44ad76beeb7ab53251668a21f8d",
"uniswapBridge": "0x0e85f89f29998df65402391478e5924700c0079d",
"uniswapV2Bridge": "0x7b3530a635d099de0534dc27e46cd7c57578c3c8",
"eth2DaiBridge": "0x2d47147429b474d2e4f83e658015858a1312ed5b",
"erc20BridgeSampler": "0xcf9e66851f274aa4721e54526117876d90d51aa1",
"kyberBridge": "0xaecfa25920f892b6eb496e1f6e84037f59da7f44",
"chaiBridge": "0x0000000000000000000000000000000000000000",
"dydxBridge": "0xc213707de0454008758071c2edc1365621b8a5c5",
"godsUnchainedValidator": "0x0000000000000000000000000000000000000000",
"broker": "0xcdeb6d90ee7c96b4c713f7bb4f8604981f7ebe9d",
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
"curveBridge": "0x81c0ab53a7352d2e97f682a37cba44e54647eefb",
"maximumGasPrice": "0x67a094cf028221ffdd93fc658f963151d05e2a74",
"dexForwarderBridge": "0x985d1a95c6a86a3bf85c4d425af984abceaf01de",
"multiBridge": "0x0000000000000000000000000000000000000000",
"balancerBridge": "0x407b4128e9ecad8769b2332312a9f655cb9f5f3a",
"bancorBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x618f9c67ce7bf1a50afa1e7e0238422601b0ff6e",
"exchangeProxy": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
"exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb",
"exchangeProxyTransformerDeployer": "0x1b62de2dbb5e7aa519e9c442721ecef75702807f",
"exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18",
"mStableBridge": "0x0000000000000000000000000000000000000000",
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
"shellBridge": "0x0000000000000000000000000000000000000000",
"dodoBridge": "0x0000000000000000000000000000000000000000",
"creamBridge": "0x0000000000000000000000000000000000000000",
"transformers": {
"wethTransformer": "0x9ce35b5ee9e710535e3988e3f8731d9ca9dba17d",
"payTakerTransformer": "0x5a53e7b02a83aa9f60ccf4e424f0442c255bc977",
@ -235,33 +179,19 @@
"zrxVault": "0xf23276778860e420acfc18ebeebf7e829b06965c",
"staking": "0x8a063452f7df2614db1bca3a85ef35da40cf0835",
"stakingProxy": "0x59adefa01843c627ba5d6aa350292b4b7ccae67a",
"uniswapBridge": "0x0000000000000000000000000000000000000000",
"uniswapV2Bridge": "0x0000000000000000000000000000000000000000",
"eth2DaiBridge": "0x0000000000000000000000000000000000000000",
"erc20BridgeSampler": "0x0000000000000000000000000000000000000000",
"kyberBridge": "0x0000000000000000000000000000000000000000",
"chaiBridge": "0x0000000000000000000000000000000000000000",
"dydxBridge": "0x0000000000000000000000000000000000000000",
"godsUnchainedValidator": "0x0000000000000000000000000000000000000000",
"broker": "0x0000000000000000000000000000000000000000",
"chainlinkStopLimit": "0x0000000000000000000000000000000000000000",
"curveBridge": "0x0000000000000000000000000000000000000000",
"maximumGasPrice": "0x0000000000000000000000000000000000000000",
"dexForwarderBridge": "0x0000000000000000000000000000000000000000",
"multiBridge": "0x0000000000000000000000000000000000000000",
"balancerBridge": "0x0000000000000000000000000000000000000000",
"bancorBridge": "0x0000000000000000000000000000000000000000",
"exchangeProxyGovernor": "0x0000000000000000000000000000000000000000",
"exchangeProxy": "0x5315e44798395d4a952530d131249fe00f554565",
"exchangeProxyAllowanceTarget": "0x8362c3ebd90041b30ec45908332e592721642637",
"exchangeProxyTransformerDeployer": "0x5409ed021d9299bf6814279a6a1411a7e866a631",
"exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa",
"mStableBridge": "0x0000000000000000000000000000000000000000",
"mooniswapBridge": "0x0000000000000000000000000000000000000000",
"sushiswapBridge": "0x0000000000000000000000000000000000000000",
"shellBridge": "0x0000000000000000000000000000000000000000",
"dodoBridge": "0x0000000000000000000000000000000000000000",
"creamBridge": "0x0000000000000000000000000000000000000000",
"transformers": {
"wethTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5",
"payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3",

View File

@ -21,32 +21,18 @@ export interface ContractAddresses {
stakingProxy: string;
erc20BridgeProxy: string;
erc20BridgeSampler: string;
uniswapBridge: string;
uniswapV2Bridge: string;
eth2DaiBridge: string;
kyberBridge: string;
chaiBridge: string;
dydxBridge: string;
curveBridge: string;
godsUnchainedValidator: string;
broker: string;
chainlinkStopLimit: string;
maximumGasPrice: string;
dexForwarderBridge: string;
multiBridge: string;
balancerBridge: string;
bancorBridge: string;
exchangeProxyGovernor: string;
exchangeProxy: string;
exchangeProxyAllowanceTarget: string;
exchangeProxyTransformerDeployer: string;
exchangeProxyFlashWallet: string;
mStableBridge: string;
mooniswapBridge: string;
sushiswapBridge: string;
shellBridge: string;
dodoBridge: string;
creamBridge: string;
transformers: {
wethTransformer: string;
payTakerTransformer: string;

View File

@ -317,16 +317,22 @@ export async function runMigrationsAsync(
mooniswapBridge: NULL_ADDRESS,
mStableBridge: NULL_ADDRESS,
oasisBridge: NULL_ADDRESS,
swerveBridge: NULL_ADDRESS,
sushiswapBridge: NULL_ADDRESS,
uniswapBridge: NULL_ADDRESS,
uniswapV2Bridge: NULL_ADDRESS,
kyberNetworkProxy: NULL_ADDRESS,
oasis: NULL_ADDRESS,
sushiswapRouter: NULL_ADDRESS,
uniswapV2Router: NULL_ADDRESS,
uniswapExchangeFactory: NULL_ADDRESS,
mStable: NULL_ADDRESS,
shellBridge: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
shell: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
dodoHelper: NULL_ADDRESS,
snowSwapBridge: NULL_ADDRESS,
weth: etherToken.address,
},
);
@ -384,29 +390,15 @@ export async function runMigrationsAsync(
zrxVault: zrxVault.address,
staking: stakingLogic.address,
stakingProxy: stakingProxy.address,
uniswapBridge: NULL_ADDRESS,
eth2DaiBridge: NULL_ADDRESS,
kyberBridge: NULL_ADDRESS,
erc20BridgeSampler: NULL_ADDRESS,
chaiBridge: NULL_ADDRESS,
dydxBridge: NULL_ADDRESS,
curveBridge: NULL_ADDRESS,
uniswapV2Bridge: NULL_ADDRESS,
godsUnchainedValidator: NULL_ADDRESS,
broker: NULL_ADDRESS,
chainlinkStopLimit: NULL_ADDRESS,
maximumGasPrice: NULL_ADDRESS,
dexForwarderBridge: NULL_ADDRESS,
multiBridge: NULL_ADDRESS,
balancerBridge: NULL_ADDRESS,
bancorBridge: NULL_ADDRESS,
exchangeProxyGovernor: NULL_ADDRESS,
mStableBridge: NULL_ADDRESS,
mooniswapBridge: NULL_ADDRESS,
sushiswapBridge: NULL_ADDRESS,
shellBridge: NULL_ADDRESS,
dodoBridge: NULL_ADDRESS,
creamBridge: NULL_ADDRESS,
exchangeProxy: exchangeProxy.address,
exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress,
exchangeProxyTransformerDeployer: txDefaults.from,