From 7e8b56eef42baa2ba9d4ca1deb6f48f294b2ee52 Mon Sep 17 00:00:00 2001 From: Jacob Evans Date: Thu, 20 Aug 2020 08:18:44 +1000 Subject: [PATCH] feat: mStable + FQT Rollup (#2662) * feat: mStable * deploy and CHANGELOG * `@0x/contracts-utils`: Add more testnet addresses. * `@0x/contract-addresses`: Deply Mstable on testnets * `@0x/contract-addresses`: Remove testnet deployments of mStable :-) * move `erc20-bridge-sampler` into `asset-swapper` remove `DevUtils` dependency from sampler contract. * `@0x/asset-swapper`: Add ERC20BridgeSampler support for validating orders in maker fees denominated in non-maker assets. `@0x/asset-swapper`: Add tests for `NativeOrderSampler`. * `@0x/asset-swapper`: Return `0` sample if native order asset data is unsupported. * `@0x/asset-swapper`: Fix failing test. * feat: ExchangeProxy FQT fruit rollup (#2645) * feat: Optimize Bridges in ExchangeProxy * compile and most work * work around to trust the delecall contract * force allowances * Update Kyber/Eth2Dai bridges * Remove memory state where not required * cleanup * Combine Bridges into one adapter * mixins * refactor out ZeroExBridge * move out interface * comment out hacks * update migrations * remove simbot hacks * AdapterAddresses and mStable * Share constructor arg * fix migration * Remove whitespace * `@0x/contracts-zero-ex`: BridgeAdapter -- revert if bridge address is 0. * `@0x/contract-addresses`: Deploy FQT. Co-authored-by: Lawrence Forman Co-authored-by: Lawrence Forman * update ganache contract addresses * fix: asset-swapper empty batch call (#2669) * update ganache contract addresses * fix: asset-swapper prevent empty sampler batch call * add sampler to migrations * change migrations version * Use contract-wrappers and artifacts * remove extra data * remove deps, set sampler to NULL_ADDRESS * all the exports * noop sell rate too * update ganache contract addresses Co-authored-by: Lawrence Forman Co-authored-by: Lawrence Forman --- .prettierignore | 8 +- contracts/asset-proxy/CHANGELOG.json | 4 + .../contracts/src/bridges/MStableBridge.sol | 94 + .../contracts/src/interfaces/IMStable.sol | 32 + contracts/asset-proxy/package.json | 2 +- contracts/asset-proxy/src/artifacts.ts | 4 + contracts/asset-proxy/src/wrappers.ts | 2 + contracts/asset-proxy/test/artifacts.ts | 4 + contracts/asset-proxy/test/wrappers.ts | 2 + contracts/asset-proxy/tsconfig.json | 4 + contracts/erc20-bridge-sampler/.npmignore | 10 - contracts/erc20-bridge-sampler/CHANGELOG.json | 210 --- contracts/erc20-bridge-sampler/CHANGELOG.md | 83 - contracts/erc20-bridge-sampler/DEPLOYS.json | 1 - contracts/erc20-bridge-sampler/README.md | 67 - .../contracts/src/IDevUtils.sol | 45 - .../contracts/src/NativeOrderSampler.sol | 125 -- contracts/erc20-bridge-sampler/package.json | 93 - contracts/erc20-bridge-sampler/src/index.ts | 2 - .../erc20-bridge-sampler/truffle-config.js | 96 - contracts/erc20-bridge-sampler/tsconfig.json | 39 - contracts/erc20-bridge-sampler/tslint.json | 10 - contracts/integrations/package.json | 1 - .../contracts/src/DeploymentConstants.sol | 180 +- .../contracts/src/bridges/BridgeAdapter.sol | 172 ++ .../contracts/src/bridges/IBridgeAdapter.sol | 30 + .../bridges/mixins/MixinAdapterAddresses.sol | 42 + .../src/bridges/mixins/MixinBalancer.sol | 74 + .../src/bridges/mixins/MixinCurve.sol | 70 + .../src/bridges/mixins/MixinKyber.sol | 123 ++ .../src/bridges/mixins/MixinMStable.sol | 74 + .../src/bridges/mixins/MixinOasis.sol | 84 + .../src/bridges/mixins/MixinUniswap.sol | 220 +++ .../src/bridges/mixins/MixinUniswapV2.sol | 100 + .../src/bridges/mixins/MixinZeroExBridge.sol | 76 + .../contracts/src/fixins/FixinGasToken.sol | 46 - .../src/transformers/FillQuoteTransformer.sol | 87 +- .../test/TestFillQuoteTransformerBridge.sol | 3 +- contracts/zero-ex/package.json | 4 +- contracts/zero-ex/src/artifacts.ts | 2 + contracts/zero-ex/src/index.ts | 68 +- contracts/zero-ex/src/wrappers.ts | 1 + contracts/zero-ex/test/artifacts.ts | 24 +- .../fill_quote_transformer_test.ts | 31 +- contracts/zero-ex/test/wrappers.ts | 12 +- contracts/zero-ex/tsconfig.json | 13 +- package.json | 2 +- packages/asset-swapper/.gitignore | 2 + packages/asset-swapper/.npmignore | 2 + packages/asset-swapper/.solhint.json | 21 + packages/asset-swapper/CHANGELOG.json | 8 + .../asset-swapper}/compiler.json | 0 .../contracts/src/ApproximateBuys.sol | 0 .../contracts/src/CurveSampler.sol | 0 .../contracts/src/DummyLiquidityProvider.sol | 0 .../src/DummyLiquidityProviderRegistry.sol | 0 .../contracts/src/ERC20BridgeSampler.sol | 15 +- .../contracts/src/Eth2DaiSampler.sol | 0 .../asset-swapper}/contracts/src/ICurve.sol | 0 .../asset-swapper}/contracts/src/IEth2Dai.sol | 0 .../contracts/src/IKyberHintHandler.sol | 0 .../contracts/src/IKyberNetwork.sol | 0 .../contracts/src/IKyberNetworkProxy.sol | 0 .../contracts/src/IKyberStorage.sol | 0 .../contracts/src/ILiquidityProvider.sol | 0 .../src/ILiquidityProviderRegistry.sol | 0 .../asset-swapper/contracts/src/IMStable.sol | 32 + .../contracts/src/IMultiBridge.sol | 0 .../contracts/src/IUniswapExchangeQuotes.sol | 0 .../contracts/src/IUniswapV2Router01.sol | 0 .../contracts/src/KyberSampler.sol | 0 .../src/LiquidityProviderSampler.sol | 3 + .../contracts/src/MStableSampler.sol | 126 ++ .../contracts/src/MultiBridgeSampler.sol | 0 .../contracts/src/NativeOrderSampler.sol | 205 +++ .../contracts/src/SamplerUtils.sol | 0 .../contracts/src/UniswapSampler.sol | 0 .../contracts/src/UniswapV2Sampler.sol | 0 .../contracts/test/TestERC20BridgeSampler.sol | 31 +- .../contracts/test/TestNativeOrderSampler.sol | 109 ++ packages/asset-swapper/package.json | 33 +- .../asset-swapper}/src/artifacts.ts | 0 packages/asset-swapper/src/index.ts | 44 +- packages/asset-swapper/src/swap_quoter.ts | 7 +- .../utils/market_operation_utils/constants.ts | 2 + .../src/utils/market_operation_utils/index.ts | 6 +- .../utils/market_operation_utils/orders.ts | 2 + .../utils/market_operation_utils/sampler.ts | 19 +- .../sampler_operations.ts | 100 +- .../src/utils/market_operation_utils/types.ts | 3 +- .../asset-swapper}/src/wrappers.ts | 0 .../asset-swapper}/test/artifacts.ts | 8 +- .../contracts}/bridge_sampler_mainnet_test.ts | 6 +- .../contracts/erc20_bridge_sampler_test.ts | 92 +- .../contracts/native_order_sampler_test.ts | 313 ++++ .../asset-swapper/test/dex_sampler_test.ts | 10 +- .../test/market_operation_utils_test.ts | 36 +- .../test/utils/mock_sampler_contract.ts | 5 +- .../asset-swapper}/test/wrappers.ts | 4 +- packages/asset-swapper/tsconfig.json | 42 +- packages/asset-swapper/tslint.json | 8 +- packages/contract-addresses/CHANGELOG.json | 8 + packages/contract-addresses/addresses.json | 29 +- packages/contract-addresses/src/index.ts | 1 + .../artifacts/ERC20BridgeSampler.json | 504 ----- packages/contract-artifacts/src/index.ts | 2 - packages/contract-artifacts/tsconfig.json | 1 - .../erc20_bridge_sampler.ts | 1631 ----------------- .../i_erc20_bridge_sampler.ts | 1564 ---------------- packages/contract-wrappers/src/index.ts | 242 ++- packages/migrations/package.json | 2 - packages/migrations/src/migration.ts | 455 ++--- tsconfig.json | 1 - 113 files changed, 2891 insertions(+), 5319 deletions(-) create mode 100644 contracts/asset-proxy/contracts/src/bridges/MStableBridge.sol create mode 100644 contracts/asset-proxy/contracts/src/interfaces/IMStable.sol delete mode 100644 contracts/erc20-bridge-sampler/.npmignore delete mode 100644 contracts/erc20-bridge-sampler/CHANGELOG.json delete mode 100644 contracts/erc20-bridge-sampler/CHANGELOG.md delete mode 100644 contracts/erc20-bridge-sampler/DEPLOYS.json delete mode 100644 contracts/erc20-bridge-sampler/README.md delete mode 100644 contracts/erc20-bridge-sampler/contracts/src/IDevUtils.sol delete mode 100644 contracts/erc20-bridge-sampler/contracts/src/NativeOrderSampler.sol delete mode 100644 contracts/erc20-bridge-sampler/package.json delete mode 100644 contracts/erc20-bridge-sampler/src/index.ts delete mode 100644 contracts/erc20-bridge-sampler/truffle-config.js delete mode 100644 contracts/erc20-bridge-sampler/tsconfig.json delete mode 100644 contracts/erc20-bridge-sampler/tslint.json create mode 100644 contracts/zero-ex/contracts/src/bridges/BridgeAdapter.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/IBridgeAdapter.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinAdapterAddresses.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinBalancer.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinCurve.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinKyber.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinMStable.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinOasis.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswap.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswapV2.sol create mode 100644 contracts/zero-ex/contracts/src/bridges/mixins/MixinZeroExBridge.sol delete mode 100644 contracts/zero-ex/contracts/src/fixins/FixinGasToken.sol create mode 100644 packages/asset-swapper/.gitignore create mode 100644 packages/asset-swapper/.solhint.json rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/compiler.json (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/ApproximateBuys.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/CurveSampler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/DummyLiquidityProvider.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/DummyLiquidityProviderRegistry.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/ERC20BridgeSampler.sol (90%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/Eth2DaiSampler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/ICurve.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IEth2Dai.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IKyberHintHandler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IKyberNetwork.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IKyberNetworkProxy.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IKyberStorage.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/ILiquidityProvider.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/ILiquidityProviderRegistry.sol (100%) create mode 100644 packages/asset-swapper/contracts/src/IMStable.sol rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IMultiBridge.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IUniswapExchangeQuotes.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/IUniswapV2Router01.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/KyberSampler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/LiquidityProviderSampler.sol (98%) create mode 100644 packages/asset-swapper/contracts/src/MStableSampler.sol rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/MultiBridgeSampler.sol (100%) create mode 100644 packages/asset-swapper/contracts/src/NativeOrderSampler.sol rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/SamplerUtils.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/UniswapSampler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/src/UniswapV2Sampler.sol (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/contracts/test/TestERC20BridgeSampler.sol (93%) create mode 100644 packages/asset-swapper/contracts/test/TestNativeOrderSampler.sol rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/src/artifacts.ts (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/src/wrappers.ts (100%) rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/test/artifacts.ts (90%) rename {contracts/integrations/test/bridge_sampler => packages/asset-swapper/test/contracts}/bridge_sampler_mainnet_test.ts (97%) rename contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts => packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts (92%) create mode 100644 packages/asset-swapper/test/contracts/native_order_sampler_test.ts rename {contracts/erc20-bridge-sampler => packages/asset-swapper}/test/wrappers.ts (90%) delete mode 100644 packages/contract-artifacts/artifacts/ERC20BridgeSampler.json delete mode 100644 packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts delete mode 100644 packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts diff --git a/.prettierignore b/.prettierignore index fb54998581..e7c483a922 100644 --- a/.prettierignore +++ b/.prettierignore @@ -40,10 +40,6 @@ lib /contracts/erc20/test/generated-wrappers /contracts/erc20/generated-artifacts /contracts/erc20/test/generated-artifacts -/contracts/erc20-bridge-sampler/generated-wrappers -/contracts/erc20-bridge-sampler/test/generated-wrappers -/contracts/erc20-bridge-sampler/generated-artifacts -/contracts/erc20-bridge-sampler/test/generated-artifacts /contracts/erc721/generated-wrappers /contracts/erc721/test/generated-wrappers /contracts/erc721/generated-artifacts @@ -85,6 +81,10 @@ lib /packages/json-schemas/schemas /python-packages/json_schemas/src/zero_ex/json_schemas/schemas /packages/sra-spec/public/ +/packages/asset-swapper/generated-wrappers +/packages/asset-swapper/test/generated-wrappers +/packages/asset-swapper/generated-artifacts +/packages/asset-swapper/test/generated-artifacts package.json scripts/postpublish_utils.js packages/sol-coverage/test/fixtures/artifacts diff --git a/contracts/asset-proxy/CHANGELOG.json b/contracts/asset-proxy/CHANGELOG.json index bdd0538064..b7ff41a547 100644 --- a/contracts/asset-proxy/CHANGELOG.json +++ b/contracts/asset-proxy/CHANGELOG.json @@ -9,6 +9,10 @@ { "note": "Export DexForwarderBridgeContract", "pr": 2656 + }, + { + "note": "Added `MStableBridge`", + "pr": 2662 } ] }, diff --git a/contracts/asset-proxy/contracts/src/bridges/MStableBridge.sol b/contracts/asset-proxy/contracts/src/bridges/MStableBridge.sol new file mode 100644 index 0000000000..935cce30b4 --- /dev/null +++ b/contracts/asset-proxy/contracts/src/bridges/MStableBridge.sol @@ -0,0 +1,94 @@ +/* + + 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/IMStable.sol"; + + +contract MStableBridge is + IERC20Bridge, + IWallet, + DeploymentConstants +{ + + /// @dev Swaps specified tokens against the mStable mUSD contract + /// @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-encoded "from" token address. + /// @return success The magic bytes if successful. + // solhint-disable no-unused-vars + function bridgeTransferFrom( + address toTokenAddress, + address from, + address to, + uint256 amount, + bytes calldata bridgeData + ) + external + returns (bytes4 success) + { + // Decode the bridge data to get the `fromTokenAddress`. + (address fromTokenAddress) = abi.decode(bridgeData, (address)); + + IMStable exchange = IMStable(_getMUsdAddress()); + uint256 fromTokenBalance = IERC20Token(fromTokenAddress).balanceOf(address(this)); + // Grant an allowance to the exchange to spend `fromTokenAddress` token. + LibERC20Token.approveIfBelow(fromTokenAddress, address(exchange), fromTokenBalance); + + // Try to sell all of this contract's `fromTokenAddress` token balance. + uint256 boughtAmount = exchange.swap( + fromTokenAddress, + toTokenAddress, + fromTokenBalance, + to + ); + + emit ERC20BridgeTransfer( + fromTokenAddress, + toTokenAddress, + fromTokenBalance, + boughtAmount, + 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; + } +} diff --git a/contracts/asset-proxy/contracts/src/interfaces/IMStable.sol b/contracts/asset-proxy/contracts/src/interfaces/IMStable.sol new file mode 100644 index 0000000000..a6b0a2e2a5 --- /dev/null +++ b/contracts/asset-proxy/contracts/src/interfaces/IMStable.sol @@ -0,0 +1,32 @@ +/* + + Copyright 2020 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + + +interface IMStable { + + function swap( + address _input, + address _output, + uint256 _quantity, + address _recipient + ) + external + returns (uint256 output); +} diff --git a/contracts/asset-proxy/package.json b/contracts/asset-proxy/package.json index 994a41059b..b797642d00 100644 --- a/contracts/asset-proxy/package.json +++ b/contracts/asset-proxy/package.json @@ -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|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MultiAssetProxy|Ownable|StaticCallProxy|TestChaiBridge|TestDexForwarderBridge|TestDydxBridge|TestERC20Bridge|TestEth2DaiBridge|TestKyberBridge|TestStaticCallTarget|TestUniswapBridge|TestUniswapV2Bridge|UniswapBridge|UniswapV2Bridge).json", + "abis": "./test/generated-artifacts/@(BalancerBridge|ChaiBridge|CurveBridge|DexForwarderBridge|DydxBridge|ERC1155Proxy|ERC20BridgeProxy|ERC20Proxy|ERC721Proxy|Eth2DaiBridge|IAssetData|IAssetProxy|IAssetProxyDispatcher|IAuthorizable|IBalancerPool|IChai|ICurve|IDydx|IDydxBridge|IERC20Bridge|IEth2Dai|IGasToken|IKyberNetworkProxy|IMStable|IUniswapExchange|IUniswapExchangeFactory|IUniswapV2Router01|KyberBridge|MStableBridge|MixinAssetProxyDispatcher|MixinAuthorizable|MixinGasToken|MultiAssetProxy|Ownable|StaticCallProxy|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": { diff --git a/contracts/asset-proxy/src/artifacts.ts b/contracts/asset-proxy/src/artifacts.ts index f9fba6001f..86f387af6f 100644 --- a/contracts/asset-proxy/src/artifacts.ts +++ b/contracts/asset-proxy/src/artifacts.ts @@ -28,6 +28,7 @@ import * as IERC20Bridge from '../generated-artifacts/IERC20Bridge.json'; import * as IEth2Dai from '../generated-artifacts/IEth2Dai.json'; import * as IGasToken from '../generated-artifacts/IGasToken.json'; import * as IKyberNetworkProxy from '../generated-artifacts/IKyberNetworkProxy.json'; +import * as IMStable from '../generated-artifacts/IMStable.json'; import * as IUniswapExchange from '../generated-artifacts/IUniswapExchange.json'; import * as IUniswapExchangeFactory from '../generated-artifacts/IUniswapExchangeFactory.json'; import * as IUniswapV2Router01 from '../generated-artifacts/IUniswapV2Router01.json'; @@ -35,6 +36,7 @@ import * as KyberBridge from '../generated-artifacts/KyberBridge.json'; import * as MixinAssetProxyDispatcher from '../generated-artifacts/MixinAssetProxyDispatcher.json'; import * as MixinAuthorizable from '../generated-artifacts/MixinAuthorizable.json'; import * as MixinGasToken from '../generated-artifacts/MixinGasToken.json'; +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 StaticCallProxy from '../generated-artifacts/StaticCallProxy.json'; @@ -66,6 +68,7 @@ export const artifacts = { DydxBridge: DydxBridge as ContractArtifact, Eth2DaiBridge: Eth2DaiBridge as ContractArtifact, KyberBridge: KyberBridge as ContractArtifact, + MStableBridge: MStableBridge as ContractArtifact, MixinGasToken: MixinGasToken as ContractArtifact, UniswapBridge: UniswapBridge as ContractArtifact, UniswapV2Bridge: UniswapV2Bridge as ContractArtifact, @@ -82,6 +85,7 @@ export const artifacts = { IEth2Dai: IEth2Dai as ContractArtifact, IGasToken: IGasToken as ContractArtifact, IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact, + IMStable: IMStable as ContractArtifact, IUniswapExchange: IUniswapExchange as ContractArtifact, IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact, IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact, diff --git a/contracts/asset-proxy/src/wrappers.ts b/contracts/asset-proxy/src/wrappers.ts index d28a8871da..3660a3e0f6 100644 --- a/contracts/asset-proxy/src/wrappers.ts +++ b/contracts/asset-proxy/src/wrappers.ts @@ -26,10 +26,12 @@ export * from '../generated-wrappers/i_erc20_bridge'; export * from '../generated-wrappers/i_eth2_dai'; export * from '../generated-wrappers/i_gas_token'; export * from '../generated-wrappers/i_kyber_network_proxy'; +export * from '../generated-wrappers/i_m_stable'; export * from '../generated-wrappers/i_uniswap_exchange'; export * from '../generated-wrappers/i_uniswap_exchange_factory'; export * from '../generated-wrappers/i_uniswap_v2_router01'; export * from '../generated-wrappers/kyber_bridge'; +export * from '../generated-wrappers/m_stable_bridge'; export * from '../generated-wrappers/mixin_asset_proxy_dispatcher'; export * from '../generated-wrappers/mixin_authorizable'; export * from '../generated-wrappers/mixin_gas_token'; diff --git a/contracts/asset-proxy/test/artifacts.ts b/contracts/asset-proxy/test/artifacts.ts index da9f7da1e6..4168957c27 100644 --- a/contracts/asset-proxy/test/artifacts.ts +++ b/contracts/asset-proxy/test/artifacts.ts @@ -28,6 +28,7 @@ import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json'; import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json'; import * as IGasToken from '../test/generated-artifacts/IGasToken.json'; import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkProxy.json'; +import * as IMStable from '../test/generated-artifacts/IMStable.json'; import * as IUniswapExchange from '../test/generated-artifacts/IUniswapExchange.json'; import * as IUniswapExchangeFactory from '../test/generated-artifacts/IUniswapExchangeFactory.json'; import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json'; @@ -35,6 +36,7 @@ import * as KyberBridge from '../test/generated-artifacts/KyberBridge.json'; import * as MixinAssetProxyDispatcher from '../test/generated-artifacts/MixinAssetProxyDispatcher.json'; import * as MixinAuthorizable from '../test/generated-artifacts/MixinAuthorizable.json'; import * as MixinGasToken from '../test/generated-artifacts/MixinGasToken.json'; +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 StaticCallProxy from '../test/generated-artifacts/StaticCallProxy.json'; @@ -66,6 +68,7 @@ export const artifacts = { DydxBridge: DydxBridge as ContractArtifact, Eth2DaiBridge: Eth2DaiBridge as ContractArtifact, KyberBridge: KyberBridge as ContractArtifact, + MStableBridge: MStableBridge as ContractArtifact, MixinGasToken: MixinGasToken as ContractArtifact, UniswapBridge: UniswapBridge as ContractArtifact, UniswapV2Bridge: UniswapV2Bridge as ContractArtifact, @@ -82,6 +85,7 @@ export const artifacts = { IEth2Dai: IEth2Dai as ContractArtifact, IGasToken: IGasToken as ContractArtifact, IKyberNetworkProxy: IKyberNetworkProxy as ContractArtifact, + IMStable: IMStable as ContractArtifact, IUniswapExchange: IUniswapExchange as ContractArtifact, IUniswapExchangeFactory: IUniswapExchangeFactory as ContractArtifact, IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact, diff --git a/contracts/asset-proxy/test/wrappers.ts b/contracts/asset-proxy/test/wrappers.ts index 21ff5057b2..f37871cfda 100644 --- a/contracts/asset-proxy/test/wrappers.ts +++ b/contracts/asset-proxy/test/wrappers.ts @@ -26,10 +26,12 @@ export * from '../test/generated-wrappers/i_erc20_bridge'; export * from '../test/generated-wrappers/i_eth2_dai'; export * from '../test/generated-wrappers/i_gas_token'; export * from '../test/generated-wrappers/i_kyber_network_proxy'; +export * from '../test/generated-wrappers/i_m_stable'; export * from '../test/generated-wrappers/i_uniswap_exchange'; export * from '../test/generated-wrappers/i_uniswap_exchange_factory'; export * from '../test/generated-wrappers/i_uniswap_v2_router01'; export * from '../test/generated-wrappers/kyber_bridge'; +export * from '../test/generated-wrappers/m_stable_bridge'; export * from '../test/generated-wrappers/mixin_asset_proxy_dispatcher'; export * from '../test/generated-wrappers/mixin_authorizable'; export * from '../test/generated-wrappers/mixin_gas_token'; diff --git a/contracts/asset-proxy/tsconfig.json b/contracts/asset-proxy/tsconfig.json index bfebf7aa84..5b7ac59664 100644 --- a/contracts/asset-proxy/tsconfig.json +++ b/contracts/asset-proxy/tsconfig.json @@ -26,10 +26,12 @@ "generated-artifacts/IEth2Dai.json", "generated-artifacts/IGasToken.json", "generated-artifacts/IKyberNetworkProxy.json", + "generated-artifacts/IMStable.json", "generated-artifacts/IUniswapExchange.json", "generated-artifacts/IUniswapExchangeFactory.json", "generated-artifacts/IUniswapV2Router01.json", "generated-artifacts/KyberBridge.json", + "generated-artifacts/MStableBridge.json", "generated-artifacts/MixinAssetProxyDispatcher.json", "generated-artifacts/MixinAuthorizable.json", "generated-artifacts/MixinGasToken.json", @@ -70,10 +72,12 @@ "test/generated-artifacts/IEth2Dai.json", "test/generated-artifacts/IGasToken.json", "test/generated-artifacts/IKyberNetworkProxy.json", + "test/generated-artifacts/IMStable.json", "test/generated-artifacts/IUniswapExchange.json", "test/generated-artifacts/IUniswapExchangeFactory.json", "test/generated-artifacts/IUniswapV2Router01.json", "test/generated-artifacts/KyberBridge.json", + "test/generated-artifacts/MStableBridge.json", "test/generated-artifacts/MixinAssetProxyDispatcher.json", "test/generated-artifacts/MixinAuthorizable.json", "test/generated-artifacts/MixinGasToken.json", diff --git a/contracts/erc20-bridge-sampler/.npmignore b/contracts/erc20-bridge-sampler/.npmignore deleted file mode 100644 index bdf2b8acbe..0000000000 --- a/contracts/erc20-bridge-sampler/.npmignore +++ /dev/null @@ -1,10 +0,0 @@ -# Blacklist all files -.* -* -# Whitelist lib -!lib/**/* -# Whitelist Solidity contracts -!contracts/src/**/* -# Blacklist tests in lib -/lib/test/* -# Package specific ignore diff --git a/contracts/erc20-bridge-sampler/CHANGELOG.json b/contracts/erc20-bridge-sampler/CHANGELOG.json deleted file mode 100644 index cb32a6c40b..0000000000 --- a/contracts/erc20-bridge-sampler/CHANGELOG.json +++ /dev/null @@ -1,210 +0,0 @@ -[ - { - "version": "1.8.0", - "changes": [ - { - "note": "Refactor and support more varied curves", - "pr": 2633 - } - ] - }, - { - "version": "1.7.0", - "changes": [ - { - "note": "Pass in `DevUtils` address to required functions", - "pr": 2629 - }, - { - "note": "Use new Kyber Katalyst functions", - "pr": 2629 - } - ], - "timestamp": 1594788383 - }, - { - "version": "1.6.0", - "changes": [ - { - "note": "Pass in `DevUtils` address as a constructor parameter", - "pr": 2531 - }, - { - "note": "Sample `Curve` for buy amounts", - "pr": 2551 - }, - { - "note": "Added `sampleBuysFromKyberNetwork`", - "pr": 2551 - }, - { - "note": "Use `searchBestRate` in Kyber samples. Return 0 when Uniswap/Eth2Dai reserve", - "pr": 2575 - }, - { - "note": "Add UniswapV2", - "pr": 2595 - }, - { - "note": "Sample from MultiBridge", - "pr": 2593 - } - ], - "timestamp": 1592969527 - }, - { - "timestamp": 1583220306, - "version": "1.5.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.5.0", - "changes": [ - { - "note": "Add generic liquidity provider sampling", - "pr": 2487 - }, - { - "note": "Use liquidity provider registry in sampler", - "pr": 2499 - } - ], - "timestamp": 1582837861 - }, - { - "timestamp": 1582677073, - "version": "1.4.2", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "timestamp": 1582623685, - "version": "1.4.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.4.0", - "changes": [ - { - "note": "Added Curve contract sampling", - "pr": 2483 - } - ], - "timestamp": 1581748629 - }, - { - "version": "1.3.0", - "changes": [ - { - "note": "Catch reverts to `DevUtils` calls", - "pr": 2476 - }, - { - "note": "Remove wrapper functions and introduce `batchCall()`", - "pr": 2477 - } - ], - "timestamp": 1581204851 - }, - { - "timestamp": 1580988106, - "version": "1.2.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.2.0", - "changes": [ - { - "note": "Make source IDs static on all networks, not inherited from `DeploymentConstants`.", - "pr": 2459 - } - ], - "timestamp": 1580811564 - }, - { - "version": "1.1.0", - "changes": [ - { - "note": "Add batch functions to query quotes", - "pr": 2427 - }, - { - "note": "Early exit if a DEX sample fails", - "pr": 2427 - } - ], - "timestamp": 1579682890 - }, - { - "version": "1.0.3", - "changes": [ - { - "note": "Add gas limits to external quote calls.", - "pr": 2405 - } - ], - "timestamp": 1578272714 - }, - { - "version": "1.0.2", - "changes": [ - { - "note": "Do not query empty/unsigned orders. Swallow revets on DEX quotes.", - "pr": 2395 - } - ], - "timestamp": 1576540892 - }, - { - "timestamp": 1575931811, - "version": "1.0.1", - "changes": [ - { - "note": "Dependencies updated" - } - ] - }, - { - "version": "1.0.0", - "changes": [ - { - "note": "Created package.", - "pr": 2344 - } - ], - "timestamp": 1575296764 - }, - { - "version": "1.0.0-beta.2", - "changes": [ - { - "note": "Dependencies updated" - } - ], - "timestamp": 1575290197 - }, - { - "version": "1.0.0-beta.1", - "changes": [ - { - "note": "Created package.", - "pr": 2344 - } - ] - } -] diff --git a/contracts/erc20-bridge-sampler/CHANGELOG.md b/contracts/erc20-bridge-sampler/CHANGELOG.md deleted file mode 100644 index 7fdb4e5e75..0000000000 --- a/contracts/erc20-bridge-sampler/CHANGELOG.md +++ /dev/null @@ -1,83 +0,0 @@ - - -CHANGELOG - -## v1.7.0 - _July 15, 2020_ - - * Pass in `DevUtils` address to required functions (#2629) - * Use new Kyber Katalyst functions (#2629) - -## v1.6.0 - _June 24, 2020_ - - * Pass in `DevUtils` address as a constructor parameter (#2531) - * Sample `Curve` for buy amounts (#2551) - * Added `sampleBuysFromKyberNetwork` (#2551) - * Use `searchBestRate` in Kyber samples. Return 0 when Uniswap/Eth2Dai reserve (#2575) - * Add UniswapV2 (#2595) - * Sample from MultiBridge (#2593) - -## v1.5.1 - _March 3, 2020_ - - * Dependencies updated - -## v1.5.0 - _February 27, 2020_ - - * Add generic liquidity provider sampling (#2487) - * Use liquidity provider registry in sampler (#2499) - -## v1.4.2 - _February 26, 2020_ - - * Dependencies updated - -## v1.4.1 - _February 25, 2020_ - - * Dependencies updated - -## v1.4.0 - _February 15, 2020_ - - * Added Curve contract sampling (#2483) - -## v1.3.0 - _February 8, 2020_ - - * Catch reverts to `DevUtils` calls (#2476) - * Remove wrapper functions and introduce `batchCall()` (#2477) - -## v1.2.1 - _February 6, 2020_ - - * Dependencies updated - -## v1.2.0 - _February 4, 2020_ - - * Make source IDs static on all networks, not inherited from `DeploymentConstants`. (#2459) - -## v1.1.0 - _January 22, 2020_ - - * Add batch functions to query quotes (#2427) - * Early exit if a DEX sample fails (#2427) - -## v1.0.3 - _January 6, 2020_ - - * Add gas limits to external quote calls. (#2405) - -## v1.0.2 - _December 17, 2019_ - - * Do not query empty/unsigned orders. Swallow revets on DEX quotes. (#2395) - -## v1.0.1 - _December 9, 2019_ - - * Dependencies updated - -## v1.0.0 - _December 2, 2019_ - - * Created package. (#2344) - -## v1.0.0-beta.2 - _December 2, 2019_ - - * Dependencies updated - -## v1.0.0-beta.1 - _Invalid date_ - - * Created package. (#2344) diff --git a/contracts/erc20-bridge-sampler/DEPLOYS.json b/contracts/erc20-bridge-sampler/DEPLOYS.json deleted file mode 100644 index fe51488c70..0000000000 --- a/contracts/erc20-bridge-sampler/DEPLOYS.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/contracts/erc20-bridge-sampler/README.md b/contracts/erc20-bridge-sampler/README.md deleted file mode 100644 index 3a04e3b8bd..0000000000 --- a/contracts/erc20-bridge-sampler/README.md +++ /dev/null @@ -1,67 +0,0 @@ -## ERC20BridgeSampler - -This package contains contracts used in DEX aggregation. - -This is an MVP implementation, which agnostically samples DEXes for off-chain sorting and order generation. It is entirely read-only and never not touches any funds. - -## Installation - -**Install** - -```bash -npm install @0x/contracts-erc20-bridge-sampler --save -``` - -## Contributing - -We strongly recommend that the community help us make improvements and determine the future direction of the protocol. To report bugs within this package, please create an issue in this repository. - -For proposals regarding the 0x protocol's smart contract architecture, message format, or additional functionality, go to the [0x Improvement Proposals (ZEIPs)](https://github.com/0xProject/ZEIPs) repository and follow the contribution guidelines provided therein. - -Please read our [contribution guidelines](../../CONTRIBUTING.md) before getting started. - -### Install Dependencies - -If you don't have yarn workspaces enabled (Yarn < v1.0) - enable them: - -```bash -yarn config set workspaces-experimental true -``` - -Then install dependencies - -```bash -yarn install -``` - -### Build - -To build this package and all other monorepo packages that it depends on, run the following from the monorepo root directory: - -```bash -PKG=@0x/contracts-erc20-bridge-sampler yarn build -``` - -Or continuously rebuild on change: - -```bash -PKG=@0x/contracts-erc20-bridge-sampler yarn watch -``` - -### Clean - -```bash -yarn clean -``` - -### Lint - -```bash -yarn lint -``` - -### Run Tests - -```bash -yarn test -``` diff --git a/contracts/erc20-bridge-sampler/contracts/src/IDevUtils.sol b/contracts/erc20-bridge-sampler/contracts/src/IDevUtils.sol deleted file mode 100644 index 9d6bb53196..0000000000 --- a/contracts/erc20-bridge-sampler/contracts/src/IDevUtils.sol +++ /dev/null @@ -1,45 +0,0 @@ -/* - - 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-exchange-libs/contracts/src/LibOrder.sol"; - - -interface IDevUtils { - - /// @dev Fetches all order-relevant information needed to validate if the supplied order is fillable. - /// @param order The order structure. - /// @param signature Signature provided by maker that proves the order's authenticity. - /// `0x01` can always be provided if the signature does not need to be validated. - /// @return The orderInfo (hash, status, and `takerAssetAmount` already filled for the given order), - /// fillableTakerAssetAmount (amount of the order's `takerAssetAmount` that is fillable given all on-chain state), - /// and isValidSignature (validity of the provided signature). - /// NOTE: If the `takerAssetData` encodes data for multiple assets, `fillableTakerAssetAmount` will represent a "scaled" - /// amount, meaning it must be multiplied by all the individual asset amounts within the `takerAssetData` to get the final - /// amount of each asset that can be filled. - function getOrderRelevantState(LibOrder.Order calldata order, bytes calldata signature) - external - view - returns ( - LibOrder.OrderInfo memory orderInfo, - uint256 fillableTakerAssetAmount, - bool isValidSignature - ); -} diff --git a/contracts/erc20-bridge-sampler/contracts/src/NativeOrderSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/NativeOrderSampler.sol deleted file mode 100644 index a7798f7d42..0000000000 --- a/contracts/erc20-bridge-sampler/contracts/src/NativeOrderSampler.sol +++ /dev/null @@ -1,125 +0,0 @@ -/* - - 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-exchange-libs/contracts/src/LibOrder.sol"; -import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; -import "./IDevUtils.sol"; - - -contract NativeOrderSampler { - - /// @dev Gas limit for DevUtils calls. - uint256 constant internal DEV_UTILS_CALL_GAS = 500e3; // 500k - - /// @dev Queries the fillable taker asset amounts of native orders. - /// Effectively ignores orders that have empty signatures or - /// maker/taker asset amounts (returning 0). - /// @param orders Native orders to query. - /// @param orderSignatures Signatures for each respective order in `orders`. - /// @param devUtilsAddress Address to the DevUtils contract. - /// @return orderFillableTakerAssetAmounts How much taker asset can be filled - /// by each order in `orders`. - function getOrderFillableTakerAssetAmounts( - LibOrder.Order[] memory orders, - bytes[] memory orderSignatures, - address devUtilsAddress - ) - public - view - returns (uint256[] memory orderFillableTakerAssetAmounts) - { - orderFillableTakerAssetAmounts = new uint256[](orders.length); - for (uint256 i = 0; i != orders.length; i++) { - // Ignore orders with no signature or empty maker/taker amounts. - if (orderSignatures[i].length == 0 || - orders[i].makerAssetAmount == 0 || - orders[i].takerAssetAmount == 0) { - orderFillableTakerAssetAmounts[i] = 0; - continue; - } - // solhint-disable indent - (bool didSucceed, bytes memory resultData) = - devUtilsAddress - .staticcall - .gas(DEV_UTILS_CALL_GAS) - (abi.encodeWithSelector( - IDevUtils(devUtilsAddress).getOrderRelevantState.selector, - orders[i], - orderSignatures[i] - )); - // solhint-enable indent - if (!didSucceed) { - orderFillableTakerAssetAmounts[i] = 0; - continue; - } - ( - LibOrder.OrderInfo memory orderInfo, - uint256 fillableTakerAssetAmount, - bool isValidSignature - ) = abi.decode( - resultData, - (LibOrder.OrderInfo, uint256, bool) - ); - // The fillable amount is zero if the order is not fillable or if the - // signature is invalid. - if (orderInfo.orderStatus != LibOrder.OrderStatus.FILLABLE || - !isValidSignature) { - orderFillableTakerAssetAmounts[i] = 0; - } else { - orderFillableTakerAssetAmounts[i] = fillableTakerAssetAmount; - } - } - } - - /// @dev Queries the fillable taker asset amounts of native orders. - /// Effectively ignores orders that have empty signatures or - /// @param orders Native orders to query. - /// @param orderSignatures Signatures for each respective order in `orders`. - /// @param devUtilsAddress Address to the DevUtils contract. - /// @return orderFillableMakerAssetAmounts How much maker asset can be filled - /// by each order in `orders`. - function getOrderFillableMakerAssetAmounts( - LibOrder.Order[] memory orders, - bytes[] memory orderSignatures, - address devUtilsAddress - ) - public - view - returns (uint256[] memory orderFillableMakerAssetAmounts) - { - orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts( - orders, - orderSignatures, - devUtilsAddress - ); - // `orderFillableMakerAssetAmounts` now holds taker asset amounts, so - // convert them to maker asset amounts. - for (uint256 i = 0; i < orders.length; ++i) { - if (orderFillableMakerAssetAmounts[i] != 0) { - orderFillableMakerAssetAmounts[i] = LibMath.getPartialAmountCeil( - orderFillableMakerAssetAmounts[i], - orders[i].takerAssetAmount, - orders[i].makerAssetAmount - ); - } - } - } -} diff --git a/contracts/erc20-bridge-sampler/package.json b/contracts/erc20-bridge-sampler/package.json deleted file mode 100644 index 06c7d36e04..0000000000 --- a/contracts/erc20-bridge-sampler/package.json +++ /dev/null @@ -1,93 +0,0 @@ -{ - "name": "@0x/contracts-erc20-bridge-sampler", - "version": "1.7.0", - "engines": { - "node": ">=6.12" - }, - "description": "Sampler contracts for the 0x asset-swapper", - "main": "lib/src/index.js", - "directories": { - "test": "test" - }, - "scripts": { - "build": "yarn pre_build && tsc -b", - "build:ci": "yarn build", - "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy", - "test": "yarn run_mocha", - "rebuild_and_test": "run-s build test", - "test:coverage": "SOLIDITY_COVERAGE=true run-s build run_mocha coverage:report:text coverage:report:lcov", - "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html", - "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha", - "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit", - "compile": "sol-compiler", - "watch": "sol-compiler -w", - "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers", - "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers", - "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", - "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", - "coverage:report:text": "istanbul report text", - "coverage:report:html": "istanbul report html && open coverage/index.html", - "profiler:report:html": "istanbul report html && open coverage/index.html", - "coverage:report:lcov": "istanbul report lcov", - "test:circleci": "yarn test", - "contracts:gen": "contracts-gen generate", - "contracts:copy": "contracts-gen copy", - "lint-contracts": "solhint -c ../.solhint.json contracts/**/**/**/**/*.sol", - "compile:truffle": "truffle compile" - }, - "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|CurveSampler|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|ICurve|IDevUtils|IEth2Dai|IKyberHintHandler|IKyberNetwork|IKyberNetworkProxy|IKyberStorage|ILiquidityProvider|ILiquidityProviderRegistry|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|TestERC20BridgeSampler|UniswapSampler|UniswapV2Sampler).json" - }, - "repository": { - "type": "git", - "url": "https://github.com/0xProject/0x-monorepo.git" - }, - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/0xProject/0x-monorepo/issues" - }, - "homepage": "https://github.com/0xProject/0x-monorepo/contracts/protocol/README.md", - "devDependencies": { - "@0x/abi-gen": "^5.3.1", - "@0x/contracts-asset-proxy": "^3.4.0", - "@0x/contracts-erc20": "^3.2.1", - "@0x/contracts-exchange": "^3.2.7", - "@0x/contracts-exchange-libs": "^4.3.7", - "@0x/contracts-gen": "^2.0.10", - "@0x/contracts-test-utils": "^5.3.4", - "@0x/contracts-utils": "^4.5.1", - "@0x/dev-utils": "^3.3.0", - "@0x/sol-compiler": "^4.1.1", - "@0x/tslint-config": "^4.1.0", - "@0x/web3-wrapper": "^7.2.0", - "@types/lodash": "4.14.104", - "@types/mocha": "^5.2.7", - "@types/node": "*", - "chai": "^4.0.1", - "chai-as-promised": "^7.1.0", - "chai-bignumber": "^3.0.0", - "dirty-chai": "^2.0.1", - "make-promises-safe": "^1.1.0", - "mocha": "^6.2.0", - "npm-run-all": "^4.1.2", - "shx": "^0.2.2", - "solhint": "^1.4.1", - "truffle": "^5.0.32", - "tslint": "5.11.0", - "typescript": "3.0.1" - }, - "dependencies": { - "@0x/base-contract": "^6.2.3", - "@0x/types": "^3.2.0", - "@0x/typescript-typings": "^5.1.1", - "@0x/utils": "^5.5.1", - "ethereum-types": "^3.2.0", - "lodash": "^4.17.11" - }, - "publishConfig": { - "access": "public" - }, - "gitHead": "4f91bfd907996b2f4dd383778b50c479c2602b56" -} diff --git a/contracts/erc20-bridge-sampler/src/index.ts b/contracts/erc20-bridge-sampler/src/index.ts deleted file mode 100644 index 91dd7e0e3e..0000000000 --- a/contracts/erc20-bridge-sampler/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './wrappers'; -export * from './artifacts'; diff --git a/contracts/erc20-bridge-sampler/truffle-config.js b/contracts/erc20-bridge-sampler/truffle-config.js deleted file mode 100644 index 8c95491cdc..0000000000 --- a/contracts/erc20-bridge-sampler/truffle-config.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * Use this file to configure your truffle project. It's seeded with some - * common settings for different networks and features like migrations, - * compilation and testing. Uncomment the ones you need or modify - * them to suit your project as necessary. - * - * More information about configuration can be found at: - * - * truffleframework.com/docs/advanced/configuration - * - * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) - * to sign your transactions before they're sent to a remote public node. Infura accounts - * are available for free at: infura.io/register. - * - * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate - * public/private key pairs. If you're publishing your code to GitHub make sure you load this - * phrase from a file you've .gitignored so it doesn't accidentally become public. - * - */ - -// const HDWalletProvider = require('truffle-hdwallet-provider'); -// const infuraKey = "fj4jll3k....."; -// -// const fs = require('fs'); -// const mnemonic = fs.readFileSync(".secret").toString().trim(); - -module.exports = { - /** - * Networks define how you connect to your ethereum client and let you set the - * defaults web3 uses to send transactions. If you don't specify one truffle - * will spin up a development blockchain for you on port 9545 when you - * run `develop` or `test`. You can ask a truffle command to use a specific - * network from the command line, e.g - * - * $ truffle test --network - */ - - networks: { - // Useful for testing. The `development` name is special - truffle uses it by default - // if it's defined here and no other network is specified at the command line. - // You should run a client (like ganache-cli, geth or parity) in a separate terminal - // tab if you use this network and you must also set the `host`, `port` and `network_id` - // options below to some value. - // - // development: { - // host: "127.0.0.1", // Localhost (default: none) - // port: 8545, // Standard Ethereum port (default: none) - // network_id: "*", // Any network (default: none) - // }, - // Another network with more advanced options... - // advanced: { - // port: 8777, // Custom port - // network_id: 1342, // Custom network - // gas: 8500000, // Gas sent with each transaction (default: ~6700000) - // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) - // from:
, // Account to send txs from (default: accounts[0]) - // websockets: true // Enable EventEmitter interface for web3 (default: false) - // }, - // Useful for deploying to a public network. - // NB: It's important to wrap the provider as a function. - // ropsten: { - // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), - // network_id: 3, // Ropsten's id - // gas: 5500000, // Ropsten has a lower block limit than mainnet - // confirmations: 2, // # of confs to wait between deployments. (default: 0) - // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) - // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) - // }, - // Useful for private networks - // private: { - // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), - // network_id: 2111, // This network is yours, in the cloud. - // production: true // Treats this network as if it was a public net. (default: false) - // } - }, - - // Set default mocha options here, use special reporters etc. - mocha: { - // timeout: 100000 - }, - - // Configure your compilers - compilers: { - solc: { - version: '0.5.9', - settings: { - evmVersion: 'istanbul', - optimizer: { - enabled: true, - runs: 1000000, - details: { yul: true, deduplicate: true, cse: true, constantOptimizer: true }, - }, - }, - }, - }, -}; diff --git a/contracts/erc20-bridge-sampler/tsconfig.json b/contracts/erc20-bridge-sampler/tsconfig.json deleted file mode 100644 index 9ad2490b42..0000000000 --- a/contracts/erc20-bridge-sampler/tsconfig.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "extends": "../../tsconfig", - "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, - "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], - "files": [ - "generated-artifacts/DummyLiquidityProvider.json", - "generated-artifacts/DummyLiquidityProviderRegistry.json", - "generated-artifacts/ERC20BridgeSampler.json", - "generated-artifacts/ILiquidityProvider.json", - "generated-artifacts/ILiquidityProviderRegistry.json", - "test/generated-artifacts/ApproximateBuys.json", - "test/generated-artifacts/CurveSampler.json", - "test/generated-artifacts/DummyLiquidityProvider.json", - "test/generated-artifacts/DummyLiquidityProviderRegistry.json", - "test/generated-artifacts/ERC20BridgeSampler.json", - "test/generated-artifacts/Eth2DaiSampler.json", - "test/generated-artifacts/ICurve.json", - "test/generated-artifacts/IDevUtils.json", - "test/generated-artifacts/IEth2Dai.json", - "test/generated-artifacts/IKyberHintHandler.json", - "test/generated-artifacts/IKyberNetwork.json", - "test/generated-artifacts/IKyberNetworkProxy.json", - "test/generated-artifacts/IKyberStorage.json", - "test/generated-artifacts/ILiquidityProvider.json", - "test/generated-artifacts/ILiquidityProviderRegistry.json", - "test/generated-artifacts/IMultiBridge.json", - "test/generated-artifacts/IUniswapExchangeQuotes.json", - "test/generated-artifacts/IUniswapV2Router01.json", - "test/generated-artifacts/KyberSampler.json", - "test/generated-artifacts/LiquidityProviderSampler.json", - "test/generated-artifacts/MultiBridgeSampler.json", - "test/generated-artifacts/NativeOrderSampler.json", - "test/generated-artifacts/SamplerUtils.json", - "test/generated-artifacts/TestERC20BridgeSampler.json", - "test/generated-artifacts/UniswapSampler.json", - "test/generated-artifacts/UniswapV2Sampler.json" - ], - "exclude": ["./deploy/solc/solc_bin"] -} diff --git a/contracts/erc20-bridge-sampler/tslint.json b/contracts/erc20-bridge-sampler/tslint.json deleted file mode 100644 index 91bb1bec78..0000000000 --- a/contracts/erc20-bridge-sampler/tslint.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": ["@0x/tslint-config"], - "rules": { - "custom-no-magic-numbers": false, - "max-file-line-count": false - }, - "linterOptions": { - "exclude": ["src/artifacts.ts", "test/artifacts.ts"] - } -} diff --git a/contracts/integrations/package.json b/contracts/integrations/package.json index 5dcadf5a4b..b00f722aa8 100644 --- a/contracts/integrations/package.json +++ b/contracts/integrations/package.json @@ -57,7 +57,6 @@ "@0x/contracts-broker": "^1.1.6", "@0x/contracts-coordinator": "^3.1.7", "@0x/contracts-dev-utils": "^1.3.5", - "@0x/contracts-erc20-bridge-sampler": "^1.7.0", "@0x/contracts-exchange-forwarder": "^4.2.7", "@0x/contracts-exchange-libs": "^4.3.7", "@0x/contracts-extensions": "^6.2.1", diff --git a/contracts/utils/contracts/src/DeploymentConstants.sol b/contracts/utils/contracts/src/DeploymentConstants.sol index 0f387fbf90..93749200e6 100644 --- a/contracts/utils/contracts/src/DeploymentConstants.sol +++ b/contracts/utils/contracts/src/DeploymentConstants.sol @@ -50,90 +50,98 @@ contract DeploymentConstants { 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; - /* // 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 = address(0); - /// @dev Mainnet address of the `UniswapExchangeFactory` contract. - address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = address(0); - /// @dev Mainnet address of the `UniswapV2Router01` contract. - address constant private UNISWAP_V2_ROUTER_01_ADDRESS = address(0); - /// @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); */ + // // 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 = address(0); - /// @dev Mainnet address of the `UniswapExchangeFactory` contract. - address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = address(0); - /// @dev Mainnet address of the `UniswapV2Router01` contract. - address constant private UNISWAP_V2_ROUTER_01_ADDRESS = address(0); - /// @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); */ + // // 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); */ + // // 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. @@ -254,4 +262,14 @@ contract DeploymentConstants { { 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; + } } diff --git a/contracts/zero-ex/contracts/src/bridges/BridgeAdapter.sol b/contracts/zero-ex/contracts/src/bridges/BridgeAdapter.sol new file mode 100644 index 0000000000..412403e0ef --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/BridgeAdapter.sol @@ -0,0 +1,172 @@ +/* + + 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 "./mixins/MixinAdapterAddresses.sol"; +import "./mixins/MixinBalancer.sol"; +import "./mixins/MixinCurve.sol"; +import "./mixins/MixinKyber.sol"; +import "./mixins/MixinMStable.sol"; +import "./mixins/MixinOasis.sol"; +import "./mixins/MixinUniswap.sol"; +import "./mixins/MixinUniswapV2.sol"; +import "./mixins/MixinZeroExBridge.sol"; + +contract BridgeAdapter is + MixinAdapterAddresses, + MixinBalancer, + MixinCurve, + MixinKyber, + MixinMStable, + MixinOasis, + MixinUniswap, + MixinUniswapV2, + MixinZeroExBridge +{ + + address private immutable BALANCER_BRIDGE_ADDRESS; + address private immutable CURVE_BRIDGE_ADDRESS; + address private immutable KYBER_BRIDGE_ADDRESS; + address private immutable MSTABLE_BRIDGE_ADDRESS; + address private immutable OASIS_BRIDGE_ADDRESS; + address private immutable UNISWAP_BRIDGE_ADDRESS; + address private immutable UNISWAP_V2_BRIDGE_ADDRESS; + + /// @dev Emitted when a trade occurs. + /// @param inputToken The token the bridge is converting from. + /// @param outputToken The token the bridge is converting to. + /// @param inputTokenAmount Amount of input token. + /// @param outputTokenAmount Amount of output token. + /// @param from The bridge address, indicating the underlying source of the fill. + /// @param to The `to` address, currrently `address(this)` + event ERC20BridgeTransfer( + address inputToken, + address outputToken, + uint256 inputTokenAmount, + uint256 outputTokenAmount, + address from, + address to + ); + + constructor(AdapterAddresses memory addresses) + public + MixinBalancer() + MixinCurve() + MixinKyber(addresses) + MixinMStable(addresses) + MixinOasis(addresses) + MixinUniswap(addresses) + MixinUniswapV2(addresses) + MixinZeroExBridge() + { + BALANCER_BRIDGE_ADDRESS = addresses.balancerBridge; + CURVE_BRIDGE_ADDRESS = addresses.curveBridge; + KYBER_BRIDGE_ADDRESS = addresses.kyberBridge; + MSTABLE_BRIDGE_ADDRESS = addresses.mStableBridge; + OASIS_BRIDGE_ADDRESS = addresses.oasisBridge; + UNISWAP_BRIDGE_ADDRESS = addresses.uniswapBridge; + UNISWAP_V2_BRIDGE_ADDRESS = addresses.uniswapV2Bridge; + } + + function trade( + bytes calldata makerAssetData, + address fromTokenAddress, + uint256 sellAmount + ) + external + returns (uint256 boughtAmount) + { + ( + address toTokenAddress, + address bridgeAddress, + bytes memory bridgeData + ) = abi.decode( + makerAssetData[4:], + (address, address, bytes) + ); + require( + bridgeAddress != address(this) && bridgeAddress != address(0), + "BridgeAdapter/INVALID_BRIDGE_ADDRESS" + ); + + if (bridgeAddress == CURVE_BRIDGE_ADDRESS) { + boughtAmount = _tradeCurve( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == UNISWAP_V2_BRIDGE_ADDRESS) { + boughtAmount = _tradeUniswapV2( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == UNISWAP_BRIDGE_ADDRESS) { + boughtAmount = _tradeUniswap( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == BALANCER_BRIDGE_ADDRESS) { + boughtAmount = _tradeBalancer( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == KYBER_BRIDGE_ADDRESS) { + boughtAmount = _tradeKyber( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == MSTABLE_BRIDGE_ADDRESS) { + boughtAmount = _tradeMStable( + toTokenAddress, + sellAmount, + bridgeData + ); + } else if (bridgeAddress == OASIS_BRIDGE_ADDRESS) { + boughtAmount = _tradeOasis( + toTokenAddress, + sellAmount, + bridgeData + ); + } else { + boughtAmount = _tradeZeroExBridge( + bridgeAddress, + fromTokenAddress, + toTokenAddress, + sellAmount, + bridgeData + ); + } + + emit ERC20BridgeTransfer( + fromTokenAddress, + toTokenAddress, + sellAmount, + boughtAmount, + bridgeAddress, + address(this) + ); + + return boughtAmount; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/IBridgeAdapter.sol b/contracts/zero-ex/contracts/src/bridges/IBridgeAdapter.sol new file mode 100644 index 0000000000..5fc602a362 --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/IBridgeAdapter.sol @@ -0,0 +1,30 @@ +/* + + 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; + +interface IBridgeAdapter { + + function trade( + bytes calldata makerAssetData, + address fromTokenAddress, + uint256 sellAmount + ) + external + returns (uint256 boughtAmount); +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinAdapterAddresses.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinAdapterAddresses.sol new file mode 100644 index 0000000000..46d84d876d --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinAdapterAddresses.sol @@ -0,0 +1,42 @@ +/* + + 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; + +contract MixinAdapterAddresses +{ + + struct AdapterAddresses { + // Bridges + address balancerBridge; + address curveBridge; + address kyberBridge; + address mStableBridge; + address oasisBridge; + address uniswapBridge; + address uniswapV2Bridge; + // Exchanges + address kyberNetworkProxy; + address oasis; + address uniswapV2Router; + address uniswapExchangeFactory; + address mStable; + // Other + address weth; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinBalancer.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinBalancer.sol new file mode 100644 index 0000000000..3efb11741d --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinBalancer.sol @@ -0,0 +1,74 @@ +/* + + 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; + +import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; + +interface IBalancerPool { + /// @dev Sell `tokenAmountIn` of `tokenIn` and receive `tokenOut`. + /// @param tokenIn The token being sold + /// @param tokenAmountIn The amount of `tokenIn` to sell. + /// @param tokenOut The token being bought. + /// @param minAmountOut The minimum amount of `tokenOut` to buy. + /// @param maxPrice The maximum value for `spotPriceAfter`. + /// @return tokenAmountOut The amount of `tokenOut` bought. + /// @return spotPriceAfter The new marginal spot price of the given + /// token pair for this pool. + function swapExactAmountIn( + address tokenIn, + uint tokenAmountIn, + address tokenOut, + uint minAmountOut, + uint maxPrice + ) external returns (uint tokenAmountOut, uint spotPriceAfter); +} + +contract MixinBalancer { + + using LibERC20TokenV06 for IERC20TokenV06; + + function _tradeBalancer( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data. + (address fromTokenAddress, address poolAddress) = abi.decode( + bridgeData, + (address, address) + ); + IERC20TokenV06(fromTokenAddress).approveIfBelow( + poolAddress, + sellAmount + ); + // Sell all of this contract's `fromTokenAddress` token balance. + (boughtAmount,) = IBalancerPool(poolAddress).swapExactAmountIn( + fromTokenAddress, // tokenIn + sellAmount, // tokenAmountIn + toTokenAddress, // tokenOut + 1, // minAmountOut + uint256(-1) // maxPrice + ); + return boughtAmount; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinCurve.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinCurve.sol new file mode 100644 index 0000000000..e3707e06ad --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinCurve.sol @@ -0,0 +1,70 @@ +/* + + Copyright 2020 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.6.5; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; + +contract MixinCurve { + + using LibERC20TokenV06 for IERC20TokenV06; + using LibSafeMathV06 for uint256; + using LibRichErrorsV06 for bytes; + + + struct CurveBridgeData { + address curveAddress; + bytes4 exchangeFunctionSelector; + address fromTokenAddress; + int128 fromCoinIdx; + int128 toCoinIdx; + } + + function _tradeCurve( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data to get the Curve metadata. + CurveBridgeData memory data = abi.decode(bridgeData, (CurveBridgeData)); + IERC20TokenV06(data.fromTokenAddress).approveIfBelow(data.curveAddress, sellAmount); + uint256 beforeBalance = IERC20TokenV06(toTokenAddress).balanceOf(address(this)); + (bool success, bytes memory resultData) = + data.curveAddress.call(abi.encodeWithSelector( + data.exchangeFunctionSelector, + data.fromCoinIdx, + data.toCoinIdx, + // dx + sellAmount, + // min dy + 1 + )); + if (!success) { + resultData.rrevert(); + } + + return IERC20TokenV06(toTokenAddress).balanceOf(address(this)).safeSub(beforeBalance); + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinKyber.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinKyber.sol new file mode 100644 index 0000000000..fa37a5150a --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinKyber.sol @@ -0,0 +1,123 @@ +/* + + 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 "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; +import "./MixinAdapterAddresses.sol"; + +interface IKyberNetworkProxy { + + /// @dev Sells `sellTokenAddress` tokens for `buyTokenAddress` tokens. + /// @param sellTokenAddress Token to sell. + /// @param sellAmount Amount of tokens to sell. + /// @param buyTokenAddress Token to buy. + /// @param recipientAddress Address to send bought tokens to. + /// @param maxBuyTokenAmount A limit on the amount of tokens to buy. + /// @param minConversionRate The minimal conversion rate. If actual rate + /// is lower, trade is canceled. + /// @param walletId The wallet ID to send part of the fees + /// @return boughtAmount Amount of tokens bought. + function trade( + address sellTokenAddress, + uint256 sellAmount, + address buyTokenAddress, + address payable recipientAddress, + uint256 maxBuyTokenAmount, + uint256 minConversionRate, + address walletId + ) + external + payable + returns(uint256 boughtAmount); +} + +contract MixinKyber is + MixinAdapterAddresses +{ + + using LibERC20TokenV06 for IERC20TokenV06; + + /// @dev Address indicating the trade is using ETH + address private immutable KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; + /// @dev Mainnet address of the WETH contract. + IEtherTokenV06 private immutable WETH; + /// @dev Mainnet address of the KyberNetworkProxy contract. + IKyberNetworkProxy private immutable KYBER_NETWORK_PROXY; + + constructor(AdapterAddresses memory addresses) + public + { + WETH = IEtherTokenV06(addresses.weth); + KYBER_NETWORK_PROXY = IKyberNetworkProxy(addresses.kyberNetworkProxy); + } + + function _tradeKyber( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data to get the `fromTokenAddress`. + address fromTokenAddress = abi.decode(bridgeData, (address)); + uint256 payableAmount; + + if (fromTokenAddress != address(WETH)) { + // If the input token is not WETH, grant an allowance to the exchange + // to spend them. + IERC20TokenV06(fromTokenAddress).approveIfBelow( + address(KYBER_NETWORK_PROXY), + sellAmount + ); + } else { + // If the input token is WETH, unwrap it and attach it to the call. + fromTokenAddress = KYBER_ETH_ADDRESS; + payableAmount = sellAmount; + WETH.withdraw(payableAmount); + } + bool isToTokenWeth = toTokenAddress == address(WETH); + + // Try to sell all of this contract's input token balance through + // `KyberNetworkProxy.trade()`. + boughtAmount = KYBER_NETWORK_PROXY.trade{ value: payableAmount }( + // Input token. + fromTokenAddress, + // Sell amount. + sellAmount, + // Output token. + isToTokenWeth ? KYBER_ETH_ADDRESS : toTokenAddress, + // Transfer to this contract + address(uint160(address(this))), + // Buy as much as possible. + uint256(-1), + // Lowest minimum conversion rate + 1, + // No affiliate address. + address(0) + ); + if (isToTokenWeth) { + WETH.deposit{ value: boughtAmount }(); + } + return boughtAmount; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinMStable.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinMStable.sol new file mode 100644 index 0000000000..4b960831bb --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinMStable.sol @@ -0,0 +1,74 @@ +/* + + 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 IMStable { + + function swap( + address _input, + address _output, + uint256 _quantity, + address _recipient + ) + external + returns (uint256 output); +} + +contract MixinMStable is + MixinAdapterAddresses +{ + + using LibERC20TokenV06 for IERC20TokenV06; + + /// @dev Mainnet address of the mStable mUSD contract. + IMStable private immutable MSTABLE; + + constructor(AdapterAddresses memory addresses) + public + { + MSTABLE = IMStable(addresses.mStable); + } + + function _tradeMStable( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data to get the `fromTokenAddress`. + (address fromTokenAddress) = abi.decode(bridgeData, (address)); + // Grant an allowance to the exchange to spend `fromTokenAddress` token. + IERC20TokenV06(fromTokenAddress).approveIfBelow(address(MSTABLE), sellAmount); + + boughtAmount = MSTABLE.swap( + fromTokenAddress, + toTokenAddress, + sellAmount, + address(this) + ); + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinOasis.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinOasis.sol new file mode 100644 index 0000000000..cf1f21fe2e --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinOasis.sol @@ -0,0 +1,84 @@ +/* + + 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 IOasis { + + /// @dev Sell `sellAmount` of `fromToken` token and receive `toToken` token. + /// @param fromToken The token being sold. + /// @param sellAmount The amount of `fromToken` token being sold. + /// @param toToken The token being bought. + /// @param minFillAmount Minimum amount of `toToken` token to buy. + /// @return fillAmount Amount of `toToken` bought. + function sellAllAmount( + address fromToken, + uint256 sellAmount, + address toToken, + uint256 minFillAmount + ) + external + returns (uint256 fillAmount); +} + +contract MixinOasis is + MixinAdapterAddresses +{ + + using LibERC20TokenV06 for IERC20TokenV06; + + /// @dev Mainnet address of the Oasis `MatchingMarket` contract. + IOasis private immutable OASIS; + + constructor(AdapterAddresses memory addresses) + public + { + OASIS = IOasis(addresses.oasis); + } + + function _tradeOasis( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data to get the `fromTokenAddress`. + (address fromTokenAddress) = abi.decode(bridgeData, (address)); + // Grant an allowance to the exchange to spend `fromTokenAddress` token. + IERC20TokenV06(fromTokenAddress).approveIfBelow( + address(OASIS), + sellAmount + ); + // Try to sell all of this contract's `fromTokenAddress` token balance. + boughtAmount = OASIS.sellAllAmount( + fromTokenAddress, + sellAmount, + toTokenAddress, + // min fill amount + 1 + ); + return boughtAmount; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswap.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswap.sol new file mode 100644 index 0000000000..5fff0d88b6 --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswap.sol @@ -0,0 +1,220 @@ +/* + + 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 "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol"; +import "./MixinAdapterAddresses.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); +} + +interface IUniswapExchange { + + /// @dev Buys at least `minTokensBought` tokens with ETH and transfer them + /// to `recipient`. + /// @param minTokensBought The minimum number of tokens to buy. + /// @param deadline Time when this order expires. + /// @param recipient Who to transfer the tokens to. + /// @return tokensBought Amount of tokens bought. + function ethToTokenTransferInput( + uint256 minTokensBought, + uint256 deadline, + address recipient + ) + external + payable + returns (uint256 tokensBought); + + /// @dev Buys at least `minEthBought` ETH with tokens. + /// @param tokensSold Amount of tokens to sell. + /// @param minEthBought The minimum amount of ETH to buy. + /// @param deadline Time when this order expires. + /// @return ethBought Amount of tokens bought. + function tokenToEthSwapInput( + uint256 tokensSold, + uint256 minEthBought, + uint256 deadline + ) + external + returns (uint256 ethBought); + + /// @dev Buys at least `minTokensBought` tokens with the exchange token + /// and transfer them to `recipient`. + /// @param tokensSold Amount of tokens to sell. + /// @param minTokensBought The minimum number of tokens to buy. + /// @param minEthBought The minimum amount of intermediate ETH to buy. + /// @param deadline Time when this order expires. + /// @param recipient Who to transfer the tokens to. + /// @param toTokenAddress The token being bought. + /// @return tokensBought Amount of tokens bought. + function tokenToTokenTransferInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint256 deadline, + address recipient, + address toTokenAddress + ) + external + returns (uint256 tokensBought); + + /// @dev Buys at least `minTokensBought` tokens with the exchange token. + /// @param tokensSold Amount of tokens to sell. + /// @param minTokensBought The minimum number of tokens to buy. + /// @param minEthBought The minimum amount of intermediate ETH to buy. + /// @param deadline Time when this order expires. + /// @param toTokenAddress The token being bought. + /// @return tokensBought Amount of tokens bought. + function tokenToTokenSwapInput( + uint256 tokensSold, + uint256 minTokensBought, + uint256 minEthBought, + uint256 deadline, + address toTokenAddress + ) + external + returns (uint256 tokensBought); +} + +contract MixinUniswap is + MixinAdapterAddresses +{ + + using LibERC20TokenV06 for IERC20TokenV06; + + /// @dev Mainnet address of the WETH contract. + IEtherTokenV06 private immutable WETH; + /// @dev Mainnet address of the `UniswapExchangeFactory` contract. + IUniswapExchangeFactory private immutable UNISWAP_EXCHANGE_FACTORY; + + constructor(AdapterAddresses memory addresses) + public + { + WETH = IEtherTokenV06(addresses.weth); + UNISWAP_EXCHANGE_FACTORY = IUniswapExchangeFactory(addresses.uniswapExchangeFactory); + } + + function _tradeUniswap( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + // Decode the bridge data to get the `fromTokenAddress`. + (address fromTokenAddress) = abi.decode(bridgeData, (address)); + + // Get the exchange for the token pair. + IUniswapExchange exchange = _getUniswapExchangeForTokenPair( + fromTokenAddress, + toTokenAddress + ); + + // Convert from WETH to a token. + if (fromTokenAddress == address(WETH)) { + // Unwrap the WETH. + WETH.withdraw(sellAmount); + // Buy as much of `toTokenAddress` token with ETH as possible + boughtAmount = exchange.ethToTokenTransferInput{ value: sellAmount }( + // Minimum buy amount. + 1, + // Expires after this block. + block.timestamp, + // Recipient is `this`. + address(this) + ); + + // Convert from a token to WETH. + } else if (toTokenAddress == address(WETH)) { + // Grant the exchange an allowance. + IERC20TokenV06(fromTokenAddress).approveIfBelow( + address(exchange), + sellAmount + ); + // Buy as much ETH with `fromTokenAddress` token as possible. + boughtAmount = exchange.tokenToEthSwapInput( + // Sell all tokens we hold. + sellAmount, + // Minimum buy amount. + 1, + // Expires after this block. + block.timestamp + ); + // Wrap the ETH. + WETH.deposit{ value: boughtAmount }(); + // Convert from one token to another. + } else { + // Grant the exchange an allowance. + IERC20TokenV06(fromTokenAddress).approveIfBelow( + address(exchange), + sellAmount + ); + // Buy as much `toTokenAddress` token with `fromTokenAddress` token + boughtAmount = exchange.tokenToTokenSwapInput( + // Sell all tokens we hold. + sellAmount, + // Minimum buy amount. + 1, + // Must buy at least 1 intermediate wei of ETH. + 1, + // Expires after this block. + block.timestamp, + // Convert to `toTokenAddress`. + toTokenAddress + ); + } + + return boughtAmount; + } + + /// @dev Retrieves the uniswap exchange for a given token pair. + /// In the case of a WETH-token exchange, this will be the non-WETH token. + /// In th ecase of a token-token exchange, this will be the first token. + /// @param fromTokenAddress The address of the token we are converting from. + /// @param toTokenAddress The address of the token we are converting to. + /// @return exchange The uniswap exchange. + function _getUniswapExchangeForTokenPair( + address fromTokenAddress, + address toTokenAddress + ) + private + view + returns (IUniswapExchange exchange) + { + address exchangeTokenAddress = fromTokenAddress; + // Whichever isn't WETH is the exchange token. + if (fromTokenAddress == address(WETH)) { + exchangeTokenAddress = toTokenAddress; + } + exchange = IUniswapExchange(UNISWAP_EXCHANGE_FACTORY.getExchange(exchangeTokenAddress)); + require(address(exchange) != address(0), "NO_UNISWAP_EXCHANGE_FOR_TOKEN"); + return exchange; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswapV2.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswapV2.sol new file mode 100644 index 0000000000..612a790150 --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinUniswapV2.sol @@ -0,0 +1,100 @@ + +/* + + 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"; + +/* + UniswapV2 +*/ +interface IUniswapV2Router02 { + + /// @dev Swaps an exact amount of input tokens for as many output tokens as possible, along the route determined by the path. + /// The first element of path is the input token, the last is the output token, and any intermediate elements represent + /// intermediate pairs to trade through (if, for example, a direct pair does not exist). + /// @param amountIn The amount of input tokens to send. + /// @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert. + /// @param path An array of token addresses. path.length must be >= 2. Pools for each consecutive pair of addresses must exist and have liquidity. + /// @param to Recipient of the output tokens. + /// @param deadline Unix timestamp after which the transaction will revert. + /// @return amounts The input token amount and all subsequent output token amounts. + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts); +} + +contract MixinUniswapV2 is + MixinAdapterAddresses +{ + + using LibERC20TokenV06 for IERC20TokenV06; + + /// @dev Mainnet address of the `UniswapV2Router02` contract. + IUniswapV2Router02 private immutable UNISWAP_V2_ROUTER; + + constructor(AdapterAddresses memory addresses) + public + { + UNISWAP_V2_ROUTER = IUniswapV2Router02(addresses.uniswapV2Router); + } + + function _tradeUniswapV2( + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256) + { + // Decode the bridge data to get the `fromTokenAddress`. + // solhint-disable indent + address[] memory path = abi.decode(bridgeData, (address[])); + // solhint-enable indent + + require(path.length >= 2, "UniswapV2Bridge/PATH_LENGTH_MUST_BE_AT_LEAST_TWO"); + require(path[path.length - 1] == toTokenAddress, "UniswapV2Bridge/LAST_ELEMENT_OF_PATH_MUST_MATCH_OUTPUT_TOKEN"); + // Grant the Uniswap router an allowance. + IERC20TokenV06(path[0]).approveIfBelow( + address(UNISWAP_V2_ROUTER), + sellAmount + ); + + uint[] memory amounts = UNISWAP_V2_ROUTER.swapExactTokensForTokens( + // Sell all tokens we hold. + sellAmount, + // Minimum buy amount. + 1, + // Convert `fromTokenAddress` to `toTokenAddress`. + path, + // Recipient is `this`. + address(this), + // Expires after this block. + block.timestamp + ); + return amounts[amounts.length-1]; + } +} diff --git a/contracts/zero-ex/contracts/src/bridges/mixins/MixinZeroExBridge.sol b/contracts/zero-ex/contracts/src/bridges/mixins/MixinZeroExBridge.sol new file mode 100644 index 0000000000..7bd3fb9aca --- /dev/null +++ b/contracts/zero-ex/contracts/src/bridges/mixins/MixinZeroExBridge.sol @@ -0,0 +1,76 @@ +/* + + 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; + +import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol"; +import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol"; +import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; + +interface IERC20Bridge { + + /// @dev Transfers `amount` of the ERC20 `tokenAddress` from `from` to `to`. + /// @param tokenAddress The address of the ERC20 token to transfer. + /// @param from Address to transfer asset from. + /// @param to Address to transfer asset to. + /// @param amount Amount of asset to transfer. + /// @param bridgeData Arbitrary asset data needed by the bridge contract. + /// @return success The magic bytes `0xdc1600f3` if successful. + function bridgeTransferFrom( + address tokenAddress, + address from, + address to, + uint256 amount, + bytes calldata bridgeData + ) + external + returns (bytes4 success); +} + +contract MixinZeroExBridge { + + using LibERC20TokenV06 for IERC20TokenV06; + using LibSafeMathV06 for uint256; + + function _tradeZeroExBridge( + address bridgeAddress, + address fromTokenAddress, + address toTokenAddress, + uint256 sellAmount, + bytes memory bridgeData + ) + internal + returns (uint256 boughtAmount) + { + uint256 balanceBefore = IERC20TokenV06(toTokenAddress).balanceOf(address(this)); + // Trade the good old fashioned way + IERC20TokenV06(fromTokenAddress).compatTransfer( + bridgeAddress, + sellAmount + ); + IERC20Bridge(bridgeAddress).bridgeTransferFrom( + toTokenAddress, + bridgeAddress, + address(this), + 1, // amount to transfer back from the bridge + bridgeData + ); + + boughtAmount = IERC20TokenV06(toTokenAddress).balanceOf(address(this)).safeSub(balanceBefore); + } +} diff --git a/contracts/zero-ex/contracts/src/fixins/FixinGasToken.sol b/contracts/zero-ex/contracts/src/fixins/FixinGasToken.sol deleted file mode 100644 index 96cac324c0..0000000000 --- a/contracts/zero-ex/contracts/src/fixins/FixinGasToken.sol +++ /dev/null @@ -1,46 +0,0 @@ -/* - - Copyright 2020 ZeroEx Intl. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -*/ - -pragma solidity ^0.6.5; - -import "../vendor/v3/IGasToken.sol"; - -contract FixinGasToken -{ - /// @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 Frees gas tokens using the balance of `from`. Amount freed is based - /// on the gas consumed in the function - modifier freesGasTokensFromCollector() { - uint256 gasBefore = gasleft(); - _; - // (gasUsed + FREE_BASE) / (2 * REIMBURSE - FREE_TOKEN) - // 14154 24000 6870 - uint256 value = (gasBefore - gasleft() + 14154) / 41130; - GST_ADDRESS.call( - abi.encodeWithSelector( - IGasToken(address(0)).freeFromUpTo.selector, - GST_COLLECTOR_ADDRESS, - value - ) - ); - } -} diff --git a/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol b/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol index 3adbb48036..c2e8b10d15 100644 --- a/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol +++ b/contracts/zero-ex/contracts/src/transformers/FillQuoteTransformer.sol @@ -27,17 +27,14 @@ import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol"; import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol"; import "../errors/LibTransformERC20RichErrors.sol"; import "../vendor/v3/IExchange.sol"; -import "../vendor/v3/IERC20Bridge.sol"; +import "../bridges/IBridgeAdapter.sol"; import "./Transformer.sol"; import "./LibERC20Transformer.sol"; -import "../fixins/FixinGasToken.sol"; - /// @dev A transformer that fills an ERC20 market sell/buy quote. /// This transformer shortcuts bridge orders and fills them directly contract FillQuoteTransformer is - Transformer, - FixinGasToken + Transformer { using LibERC20TokenV06 for IERC20TokenV06; using LibERC20Transformer for IERC20TokenV06; @@ -116,15 +113,18 @@ contract FillQuoteTransformer is IExchange public immutable exchange; /// @dev The ERC20Proxy address. address public immutable erc20Proxy; + /// @dev The BridgeAdapter address + IBridgeAdapter public immutable bridgeAdapter; /// @dev Create this contract. /// @param exchange_ The Exchange V3 instance. - constructor(IExchange exchange_) + constructor(IExchange exchange_, IBridgeAdapter bridgeAdapter_) public Transformer() { exchange = exchange_; erc20Proxy = exchange_.getAssetProxy(ERC20_ASSET_PROXY_ID); + bridgeAdapter = bridgeAdapter_; } /// @dev Sell this contract's entire balance of of `sellToken` in exchange @@ -139,7 +139,6 @@ contract FillQuoteTransformer is ) external override - freesGasTokensFromCollector returns (bytes4 success) { TransformData memory data = abi.decode(data_, (TransformData)); @@ -308,7 +307,6 @@ contract FillQuoteTransformer is signature, takerTokenFillAmount, state, - makerToken, takerFeeToken == takerToken ); } @@ -372,7 +370,6 @@ contract FillQuoteTransformer is signature, takerTokenFillAmount, state, - makerToken, takerFeeToken == takerToken ); } @@ -383,7 +380,6 @@ contract FillQuoteTransformer is /// @param signature The order signature. /// @param takerAssetFillAmount How much taker asset to fill. /// @param state Intermediate state variables to get around stack limits. - /// @param makerToken The maker token. /// @param isTakerFeeInTakerToken Whether the taker fee token is the same as the /// taker token. function _fillOrder( @@ -391,7 +387,6 @@ contract FillQuoteTransformer is bytes memory signature, uint256 takerAssetFillAmount, FillState memory state, - IERC20TokenV06 makerToken, bool isTakerFeeInTakerToken ) private @@ -402,37 +397,23 @@ contract FillQuoteTransformer is takerAssetFillAmount.min256(order.takerAssetAmount); availableTakerAssetFillAmount = availableTakerAssetFillAmount.min256(state.takerTokenBalanceRemaining); - // If it is a Bridge order we fill this directly - // rather than filling via 0x Exchange + + // If it is a Bridge order we fill this directly through the BridgeAdapter if (order.makerAssetData.readBytes4(0) == ERC20_BRIDGE_PROXY_ID) { - // Calculate the amount (in maker token) we expect to receive - // from the bridge - uint256 outputTokenAmount = LibMathV06.getPartialAmountFloor( - availableTakerAssetFillAmount, - order.takerAssetAmount, - order.makerAssetAmount - ); - (bool success, bytes memory data) = address(_implementation).delegatecall( + (bool success, bytes memory resultData) = address(bridgeAdapter).delegatecall( abi.encodeWithSelector( - this.fillBridgeOrder.selector, - order.makerAddress, + IBridgeAdapter.trade.selector, order.makerAssetData, - order.takerAssetData, - availableTakerAssetFillAmount, - outputTokenAmount + address(_getTokenFromERC20AssetData(order.takerAssetData)), + availableTakerAssetFillAmount ) ); - // Swallow failures, leaving all results as zero. - // TransformERC20 asserts the overall price is as expected. It is possible - // a subsequent fill can net out at the expected price so we do not assert - // the trade balance if (success) { - results.makerTokenBoughtAmount = makerToken - .balanceOf(address(this)) - .safeSub(state.boughtAmount); + results.makerTokenBoughtAmount = abi.decode(resultData, (uint256)); results.takerTokenSoldAmount = availableTakerAssetFillAmount; // protocol fee paid remains 0 } + return results; } else { // Emit an event if we do not have sufficient ETH to cover the protocol fee. if (state.ethRemaining < state.protocolFee) { @@ -460,46 +441,6 @@ contract FillQuoteTransformer is } } - /// @dev Attempt to fill an ERC20 Bridge order. If the fill reverts, - /// or the amount filled was not sufficient this reverts. - /// @param makerAddress The address of the maker. - /// @param makerAssetData The encoded ERC20BridgeProxy asset data. - /// @param takerAssetData The encoded ERC20 asset data. - /// @param inputTokenAmount How much taker asset to fill clamped to the available balance. - /// @param outputTokenAmount How much maker asset to receive. - function fillBridgeOrder( - address makerAddress, - bytes calldata makerAssetData, - bytes calldata takerAssetData, - uint256 inputTokenAmount, - uint256 outputTokenAmount - ) - external - { - // Track changes in the maker token balance. - ( - address tokenAddress, - address bridgeAddress, - bytes memory bridgeData - ) = abi.decode( - makerAssetData.sliceDestructive(4, makerAssetData.length), - (address, address, bytes) - ); - require(bridgeAddress != address(this), "INVALID_BRIDGE_ADDRESS"); - // Transfer the tokens to the bridge to perform the work - _getTokenFromERC20AssetData(takerAssetData).compatTransfer( - bridgeAddress, - inputTokenAmount - ); - IERC20Bridge(bridgeAddress).bridgeTransferFrom( - tokenAddress, - makerAddress, - address(this), - outputTokenAmount, // amount to transfer back from the bridge - bridgeData - ); - } - /// @dev Extract the token from plain ERC20 asset data. /// If the asset-data is empty, a zero token address will be returned. /// @param assetData The order asset data. diff --git a/contracts/zero-ex/contracts/test/TestFillQuoteTransformerBridge.sol b/contracts/zero-ex/contracts/test/TestFillQuoteTransformerBridge.sol index 8bf6fbdcc7..7b8608ed2b 100644 --- a/contracts/zero-ex/contracts/test/TestFillQuoteTransformerBridge.sol +++ b/contracts/zero-ex/contracts/test/TestFillQuoteTransformerBridge.sol @@ -29,6 +29,7 @@ contract TestFillQuoteTransformerBridge { struct FillBehavior { // Scaling for maker assets minted, in 1e18. uint256 makerAssetMintRatio; + uint256 amount; } bytes4 private constant ERC20_BRIDGE_PROXY_ID = 0xdc1600f3; @@ -49,7 +50,7 @@ contract TestFillQuoteTransformerBridge { LibMathV06.getPartialAmountFloor( behavior.makerAssetMintRatio, 1e18, - amount + behavior.amount ) ); return ERC20_BRIDGE_PROXY_ID; diff --git a/contracts/zero-ex/package.json b/contracts/zero-ex/package.json index fed17c3770..251ebde18e 100644 --- a/contracts/zero-ex/package.json +++ b/contracts/zero-ex/package.json @@ -39,9 +39,9 @@ "publish:private": "yarn build && gitpkg publish" }, "config": { - "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer,Ownable,SimpleFunctionRegistry,TransformERC20,TokenSpender,AffiliateFeeTransformer,SignatureValidator,MetaTransactions", + "publicInterfaceContracts": "IZeroEx,ZeroEx,FullMigration,InitialMigration,IFlashWallet,IAllowanceTarget,IERC20Transformer,IOwnable,ISimpleFunctionRegistry,ITokenSpender,ITransformERC20,FillQuoteTransformer,PayTakerTransformer,WethTransformer,Ownable,SimpleFunctionRegistry,TransformERC20,TokenSpender,AffiliateFeeTransformer,SignatureValidator,MetaTransactions,BridgeAdapter", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|Bootstrap|FillQuoteTransformer|FixinCommon|FixinEIP712|FixinGasToken|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|IMetaTransactions|IOwnable|ISignatureValidator|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|MetaTransactions|Ownable|PayTakerTransformer|SignatureValidator|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json" + "abis": "./test/generated-artifacts/@(AffiliateFeeTransformer|AllowanceTarget|Bootstrap|BridgeAdapter|FillQuoteTransformer|FixinCommon|FixinEIP712|FlashWallet|FullMigration|IAllowanceTarget|IBootstrap|IBridgeAdapter|IERC20Bridge|IERC20Transformer|IExchange|IFeature|IFlashWallet|IGasToken|IMetaTransactions|IOwnable|ISignatureValidator|ISimpleFunctionRegistry|ITestSimpleFunctionRegistryFeature|ITokenSpender|ITransformERC20|IZeroEx|InitialMigration|LibBootstrap|LibCommonRichErrors|LibERC20Transformer|LibMetaTransactionsRichErrors|LibMetaTransactionsStorage|LibMigrate|LibOwnableRichErrors|LibOwnableStorage|LibProxyRichErrors|LibProxyStorage|LibSignatureRichErrors|LibSignedCallData|LibSimpleFunctionRegistryRichErrors|LibSimpleFunctionRegistryStorage|LibSpenderRichErrors|LibStorage|LibTokenSpenderStorage|LibTransformERC20RichErrors|LibTransformERC20Storage|LibWalletRichErrors|MetaTransactions|MixinAdapterAddresses|MixinBalancer|MixinCurve|MixinKyber|MixinMStable|MixinOasis|MixinUniswap|MixinUniswapV2|MixinZeroExBridge|Ownable|PayTakerTransformer|SignatureValidator|SimpleFunctionRegistry|TestCallTarget|TestDelegateCaller|TestFillQuoteTransformerBridge|TestFillQuoteTransformerExchange|TestFillQuoteTransformerHost|TestFullMigration|TestInitialMigration|TestMetaTransactionsTransformERC20Feature|TestMigrator|TestMintTokenERC20Transformer|TestMintableERC20Token|TestSimpleFunctionRegistryFeatureImpl1|TestSimpleFunctionRegistryFeatureImpl2|TestTokenSpender|TestTokenSpenderERC20Token|TestTransformERC20|TestTransformerBase|TestTransformerDeployerTransformer|TestTransformerHost|TestWeth|TestWethTransformerHost|TestZeroExFeature|TokenSpender|TransformERC20|Transformer|TransformerDeployer|WethTransformer|ZeroEx).json" }, "repository": { "type": "git", diff --git a/contracts/zero-ex/src/artifacts.ts b/contracts/zero-ex/src/artifacts.ts index b2e9d5b32f..fc0e25c8a8 100644 --- a/contracts/zero-ex/src/artifacts.ts +++ b/contracts/zero-ex/src/artifacts.ts @@ -6,6 +6,7 @@ import { ContractArtifact } from 'ethereum-types'; import * as AffiliateFeeTransformer from '../generated-artifacts/AffiliateFeeTransformer.json'; +import * as BridgeAdapter from '../generated-artifacts/BridgeAdapter.json'; import * as FillQuoteTransformer from '../generated-artifacts/FillQuoteTransformer.json'; import * as FullMigration from '../generated-artifacts/FullMigration.json'; import * as IAllowanceTarget from '../generated-artifacts/IAllowanceTarget.json'; @@ -48,4 +49,5 @@ export const artifacts = { AffiliateFeeTransformer: AffiliateFeeTransformer as ContractArtifact, SignatureValidator: SignatureValidator as ContractArtifact, MetaTransactions: MetaTransactions as ContractArtifact, + BridgeAdapter: BridgeAdapter as ContractArtifact, }; diff --git a/contracts/zero-ex/src/index.ts b/contracts/zero-ex/src/index.ts index 20e030544c..ee15391e57 100644 --- a/contracts/zero-ex/src/index.ts +++ b/contracts/zero-ex/src/index.ts @@ -1,6 +1,40 @@ +export { ZeroExRevertErrors } from '@0x/utils'; +export { + AbiDefinition, + CompilerOpts, + CompilerSettings, + CompilerSettingsMetadata, + ConstructorAbi, + ConstructorStateMutability, + ContractAbi, + ContractArtifact, + ContractChainData, + ContractChains, + DataItem, + DevdocOutput, + EventAbi, + EventParameter, + EvmBytecodeOutput, + EvmBytecodeOutputLinkReferences, + EvmOutput, + FallbackAbi, + FunctionAbi, + MethodAbi, + OptimizerSettings, + OutputField, + ParamDescription, + RevertErrorAbi, + StandardContractOutput, + StateMutability, + TupleDataItem, +} from 'ethereum-types'; export { artifacts } from './artifacts'; +export * from './migration'; +export * from './nonce_utils'; +export * from './signed_call_data'; export { AffiliateFeeTransformerContract, + BridgeAdapterContract, FillQuoteTransformerContract, IOwnableContract, IOwnableEvents, @@ -13,37 +47,3 @@ export { WethTransformerContract, ZeroExContract, } from './wrappers'; -export { ZeroExRevertErrors } from '@0x/utils'; -export { - ContractArtifact, - ContractChains, - CompilerOpts, - StandardContractOutput, - CompilerSettings, - ContractChainData, - ContractAbi, - DevdocOutput, - EvmOutput, - CompilerSettingsMetadata, - OptimizerSettings, - OutputField, - ParamDescription, - EvmBytecodeOutput, - EvmBytecodeOutputLinkReferences, - AbiDefinition, - FunctionAbi, - EventAbi, - RevertErrorAbi, - EventParameter, - DataItem, - MethodAbi, - ConstructorAbi, - FallbackAbi, - ConstructorStateMutability, - TupleDataItem, - StateMutability, -} from 'ethereum-types'; - -export * from './nonce_utils'; -export * from './migration'; -export * from './signed_call_data'; diff --git a/contracts/zero-ex/src/wrappers.ts b/contracts/zero-ex/src/wrappers.ts index 156e6816ec..ef626d0422 100644 --- a/contracts/zero-ex/src/wrappers.ts +++ b/contracts/zero-ex/src/wrappers.ts @@ -4,6 +4,7 @@ * ----------------------------------------------------------------------------- */ export * from '../generated-wrappers/affiliate_fee_transformer'; +export * from '../generated-wrappers/bridge_adapter'; export * from '../generated-wrappers/fill_quote_transformer'; export * from '../generated-wrappers/full_migration'; export * from '../generated-wrappers/i_allowance_target'; diff --git a/contracts/zero-ex/test/artifacts.ts b/contracts/zero-ex/test/artifacts.ts index c8db1d2135..70a5b4b55f 100644 --- a/contracts/zero-ex/test/artifacts.ts +++ b/contracts/zero-ex/test/artifacts.ts @@ -8,14 +8,15 @@ import { ContractArtifact } from 'ethereum-types'; import * as AffiliateFeeTransformer from '../test/generated-artifacts/AffiliateFeeTransformer.json'; import * as AllowanceTarget from '../test/generated-artifacts/AllowanceTarget.json'; import * as Bootstrap from '../test/generated-artifacts/Bootstrap.json'; +import * as BridgeAdapter from '../test/generated-artifacts/BridgeAdapter.json'; import * as FillQuoteTransformer from '../test/generated-artifacts/FillQuoteTransformer.json'; import * as FixinCommon from '../test/generated-artifacts/FixinCommon.json'; import * as FixinEIP712 from '../test/generated-artifacts/FixinEIP712.json'; -import * as FixinGasToken from '../test/generated-artifacts/FixinGasToken.json'; import * as FlashWallet from '../test/generated-artifacts/FlashWallet.json'; import * as FullMigration from '../test/generated-artifacts/FullMigration.json'; import * as IAllowanceTarget from '../test/generated-artifacts/IAllowanceTarget.json'; import * as IBootstrap from '../test/generated-artifacts/IBootstrap.json'; +import * as IBridgeAdapter from '../test/generated-artifacts/IBridgeAdapter.json'; import * as IERC20Bridge from '../test/generated-artifacts/IERC20Bridge.json'; import * as IERC20Transformer from '../test/generated-artifacts/IERC20Transformer.json'; import * as IExchange from '../test/generated-artifacts/IExchange.json'; @@ -52,6 +53,15 @@ import * as LibTransformERC20RichErrors from '../test/generated-artifacts/LibTra import * as LibTransformERC20Storage from '../test/generated-artifacts/LibTransformERC20Storage.json'; import * as LibWalletRichErrors from '../test/generated-artifacts/LibWalletRichErrors.json'; import * as MetaTransactions from '../test/generated-artifacts/MetaTransactions.json'; +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 MixinKyber from '../test/generated-artifacts/MixinKyber.json'; +import * as MixinMStable from '../test/generated-artifacts/MixinMStable.json'; +import * as MixinOasis from '../test/generated-artifacts/MixinOasis.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'; import * as Ownable from '../test/generated-artifacts/Ownable.json'; import * as PayTakerTransformer from '../test/generated-artifacts/PayTakerTransformer.json'; import * as SignatureValidator from '../test/generated-artifacts/SignatureValidator.json'; @@ -87,6 +97,17 @@ import * as ZeroEx from '../test/generated-artifacts/ZeroEx.json'; export const artifacts = { IZeroEx: IZeroEx as ContractArtifact, ZeroEx: ZeroEx as ContractArtifact, + BridgeAdapter: BridgeAdapter as ContractArtifact, + IBridgeAdapter: IBridgeAdapter as ContractArtifact, + MixinAdapterAddresses: MixinAdapterAddresses as ContractArtifact, + MixinBalancer: MixinBalancer as ContractArtifact, + MixinCurve: MixinCurve as ContractArtifact, + MixinKyber: MixinKyber as ContractArtifact, + MixinMStable: MixinMStable as ContractArtifact, + MixinOasis: MixinOasis as ContractArtifact, + MixinUniswap: MixinUniswap as ContractArtifact, + MixinUniswapV2: MixinUniswapV2 as ContractArtifact, + MixinZeroExBridge: MixinZeroExBridge as ContractArtifact, LibCommonRichErrors: LibCommonRichErrors as ContractArtifact, LibMetaTransactionsRichErrors: LibMetaTransactionsRichErrors as ContractArtifact, LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact, @@ -119,7 +140,6 @@ export const artifacts = { LibSignedCallData: LibSignedCallData as ContractArtifact, FixinCommon: FixinCommon as ContractArtifact, FixinEIP712: FixinEIP712 as ContractArtifact, - FixinGasToken: FixinGasToken as ContractArtifact, FullMigration: FullMigration as ContractArtifact, InitialMigration: InitialMigration as ContractArtifact, LibBootstrap: LibBootstrap as ContractArtifact, diff --git a/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts b/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts index 92bd69d2ef..81dc82841f 100644 --- a/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts +++ b/contracts/zero-ex/test/transformers/fill_quote_transformer_test.ts @@ -20,6 +20,7 @@ import * as _ from 'lodash'; import { artifacts } from '../artifacts'; import { TestFillQuoteTransformerBridgeContract } from '../generated-wrappers/test_fill_quote_transformer_bridge'; import { + BridgeAdapterContract, FillQuoteTransformerContract, TestFillQuoteTransformerExchangeContract, TestFillQuoteTransformerHostContract, @@ -50,12 +51,34 @@ blockchainTests.resets('FillQuoteTransformer', env => { env.txDefaults, artifacts, ); + const bridgeAdapter = await BridgeAdapterContract.deployFrom0xArtifactAsync( + artifacts.BridgeAdapter, + env.provider, + env.txDefaults, + artifacts, + { + balancerBridge: NULL_ADDRESS, + curveBridge: NULL_ADDRESS, + kyberBridge: NULL_ADDRESS, + mStableBridge: NULL_ADDRESS, + oasisBridge: NULL_ADDRESS, + uniswapBridge: NULL_ADDRESS, + uniswapV2Bridge: NULL_ADDRESS, + kyberNetworkProxy: NULL_ADDRESS, + oasis: NULL_ADDRESS, + uniswapV2Router: NULL_ADDRESS, + uniswapExchangeFactory: NULL_ADDRESS, + mStable: NULL_ADDRESS, + weth: NULL_ADDRESS, + }, + ); transformer = await FillQuoteTransformerContract.deployFrom0xArtifactAsync( artifacts.FillQuoteTransformer, env.provider, env.txDefaults, artifacts, exchange.address, + bridgeAdapter.address, ); host = await TestFillQuoteTransformerHostContract.deployFrom0xArtifactAsync( artifacts.TestFillQuoteTransformerHost, @@ -110,8 +133,9 @@ blockchainTests.resets('FillQuoteTransformer', env => { }; } - function createBridgeOrder(fields: Partial = {}, bridgeData: string = encodeBridgeBehavior()): FilledOrder { + function createBridgeOrder(fields: Partial = {}, fillRatio: Numberish = 1.0): FilledOrder { const order = createOrder(fields); + const bridgeData = encodeBridgeBehavior(order.makerAssetAmount, fillRatio); return { ...order, makerAddress: bridge.address, @@ -265,11 +289,12 @@ blockchainTests.resets('FillQuoteTransformer', env => { ); } - function encodeBridgeBehavior(makerAssetMintRatio: Numberish = 1.0): string { + function encodeBridgeBehavior(amount: BigNumber, makerAssetMintRatio: Numberish = 1.0): string { return hexUtils.slice( bridge .encodeBehaviorData({ makerAssetMintRatio: new BigNumber(makerAssetMintRatio).times('1e18').integerValue(), + amount, }) .getABIEncodedTransactionData(), 4, @@ -865,7 +890,7 @@ blockchainTests.resets('FillQuoteTransformer', env => { }); }); - describe('bridge orders', () => { + describe('bridge orders fall through', () => { it('can fully sell to a single bridge order quote', async () => { const orders = _.times(1, () => createBridgeOrder()); const signatures = orders.map(() => NULL_BYTES); diff --git a/contracts/zero-ex/test/wrappers.ts b/contracts/zero-ex/test/wrappers.ts index 5e74584ff7..9496db026f 100644 --- a/contracts/zero-ex/test/wrappers.ts +++ b/contracts/zero-ex/test/wrappers.ts @@ -6,14 +6,15 @@ export * from '../test/generated-wrappers/affiliate_fee_transformer'; export * from '../test/generated-wrappers/allowance_target'; export * from '../test/generated-wrappers/bootstrap'; +export * from '../test/generated-wrappers/bridge_adapter'; export * from '../test/generated-wrappers/fill_quote_transformer'; export * from '../test/generated-wrappers/fixin_common'; export * from '../test/generated-wrappers/fixin_e_i_p712'; -export * from '../test/generated-wrappers/fixin_gas_token'; export * from '../test/generated-wrappers/flash_wallet'; export * from '../test/generated-wrappers/full_migration'; export * from '../test/generated-wrappers/i_allowance_target'; export * from '../test/generated-wrappers/i_bootstrap'; +export * from '../test/generated-wrappers/i_bridge_adapter'; export * from '../test/generated-wrappers/i_erc20_bridge'; export * from '../test/generated-wrappers/i_erc20_transformer'; export * from '../test/generated-wrappers/i_exchange'; @@ -50,6 +51,15 @@ export * from '../test/generated-wrappers/lib_transform_erc20_rich_errors'; export * from '../test/generated-wrappers/lib_transform_erc20_storage'; export * from '../test/generated-wrappers/lib_wallet_rich_errors'; export * from '../test/generated-wrappers/meta_transactions'; +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_kyber'; +export * from '../test/generated-wrappers/mixin_m_stable'; +export * from '../test/generated-wrappers/mixin_oasis'; +export * from '../test/generated-wrappers/mixin_uniswap'; +export * from '../test/generated-wrappers/mixin_uniswap_v2'; +export * from '../test/generated-wrappers/mixin_zero_ex_bridge'; export * from '../test/generated-wrappers/ownable'; export * from '../test/generated-wrappers/pay_taker_transformer'; export * from '../test/generated-wrappers/signature_validator'; diff --git a/contracts/zero-ex/tsconfig.json b/contracts/zero-ex/tsconfig.json index e92154d08e..0acd2f5537 100644 --- a/contracts/zero-ex/tsconfig.json +++ b/contracts/zero-ex/tsconfig.json @@ -4,6 +4,7 @@ "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], "files": [ "generated-artifacts/AffiliateFeeTransformer.json", + "generated-artifacts/BridgeAdapter.json", "generated-artifacts/FillQuoteTransformer.json", "generated-artifacts/FullMigration.json", "generated-artifacts/IAllowanceTarget.json", @@ -27,14 +28,15 @@ "test/generated-artifacts/AffiliateFeeTransformer.json", "test/generated-artifacts/AllowanceTarget.json", "test/generated-artifacts/Bootstrap.json", + "test/generated-artifacts/BridgeAdapter.json", "test/generated-artifacts/FillQuoteTransformer.json", "test/generated-artifacts/FixinCommon.json", "test/generated-artifacts/FixinEIP712.json", - "test/generated-artifacts/FixinGasToken.json", "test/generated-artifacts/FlashWallet.json", "test/generated-artifacts/FullMigration.json", "test/generated-artifacts/IAllowanceTarget.json", "test/generated-artifacts/IBootstrap.json", + "test/generated-artifacts/IBridgeAdapter.json", "test/generated-artifacts/IERC20Bridge.json", "test/generated-artifacts/IERC20Transformer.json", "test/generated-artifacts/IExchange.json", @@ -71,6 +73,15 @@ "test/generated-artifacts/LibTransformERC20Storage.json", "test/generated-artifacts/LibWalletRichErrors.json", "test/generated-artifacts/MetaTransactions.json", + "test/generated-artifacts/MixinAdapterAddresses.json", + "test/generated-artifacts/MixinBalancer.json", + "test/generated-artifacts/MixinCurve.json", + "test/generated-artifacts/MixinKyber.json", + "test/generated-artifacts/MixinMStable.json", + "test/generated-artifacts/MixinOasis.json", + "test/generated-artifacts/MixinUniswap.json", + "test/generated-artifacts/MixinUniswapV2.json", + "test/generated-artifacts/MixinZeroExBridge.json", "test/generated-artifacts/Ownable.json", "test/generated-artifacts/PayTakerTransformer.json", "test/generated-artifacts/SignatureValidator.json", diff --git a/package.json b/package.json index 65fd3c1c81..3f92b673bb 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "lint:contracts": "wsrun lint -p ${npm_package_config_contractsPackages} -c --fast-exit --stages --exclude-missing" }, "config": { - "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc20-bridge-sampler @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator @0x/contracts-erc20-bridge-sampler @0x/contracts-broker @0x/contracts-zero-ex", + "contractsPackages": "@0x/contracts-asset-proxy @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-integrations @0x/contracts-multisig @0x/contracts-staking @0x/contracts-test-utils @0x/contracts-utils @0x/contracts-coordinator @0x/contracts-broker @0x/contracts-zero-ex", "mnemonic": "concert load couple harbor equip island argue ramp clarify fence smart topic", "packagesWithDocPages": "0x.js @0x/contract-wrappers @0x/connect @0x/json-schemas @0x/subproviders @0x/web3-wrapper @0x/order-utils @0x/sol-compiler @0x/sol-coverage @0x/sol-profiler @0x/sol-trace @0x/dev-utils @0x/asset-swapper @0x/migrations @0x/orderbook @0x/contracts-asset-proxy @0x/contracts-coordinator @0x/contracts-dev-utils @0x/contracts-erc20 @0x/contracts-erc721 @0x/contracts-erc1155 @0x/contracts-exchange @0x/contracts-exchange-forwarder @0x/contracts-exchange-libs @0x/contracts-extensions @0x/contracts-staking @0x/contracts-zero-ex", "ignoreDependencyVersions": "@types/styled-components @types/node", diff --git a/packages/asset-swapper/.gitignore b/packages/asset-swapper/.gitignore new file mode 100644 index 0000000000..2bd6a3f7e3 --- /dev/null +++ b/packages/asset-swapper/.gitignore @@ -0,0 +1,2 @@ +**/generated-artifacts +**/generated-wrappers diff --git a/packages/asset-swapper/.npmignore b/packages/asset-swapper/.npmignore index ea588d4859..62439cf8d0 100644 --- a/packages/asset-swapper/.npmignore +++ b/packages/asset-swapper/.npmignore @@ -3,6 +3,8 @@ * # Whitelist lib !lib/**/* +# Whitelist Solidity contracts +!contracts/src/**/* # Blacklist tests and publish scripts /lib/test/* /lib/monorepo_scripts/ diff --git a/packages/asset-swapper/.solhint.json b/packages/asset-swapper/.solhint.json new file mode 100644 index 0000000000..3090d981a1 --- /dev/null +++ b/packages/asset-swapper/.solhint.json @@ -0,0 +1,21 @@ +{ + "extends": "default", + "rules": { + "avoid-low-level-calls": false, + "avoid-tx-origin": "warn", + "bracket-align": false, + "code-complexity": false, + "compiler-fixed": false, + "const-name-snakecase": "error", + "expression-indent": "error", + "function-max-lines": false, + "func-order": "error", + "indent": ["error", 4], + "max-line-length": ["warn", 160], + "no-inline-assembly": false, + "quotes": ["error", "double"], + "separate-by-one-line-in-contract": "error", + "space-after-comma": "error", + "statement-indent": "error" + } +} diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index 985e62fc27..42f5f8e0eb 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -45,6 +45,14 @@ { "note": "Adjust fill by ethToInputRate when ethToOutputRate is 0", "pr": 2660 + }, + { + "note": "Added `mStable`", + "pr": 2662 + }, + { + "note": "Merge `erc20-bridge-sampler` into this package", + "pr": 2664 } ] }, diff --git a/contracts/erc20-bridge-sampler/compiler.json b/packages/asset-swapper/compiler.json similarity index 100% rename from contracts/erc20-bridge-sampler/compiler.json rename to packages/asset-swapper/compiler.json diff --git a/contracts/erc20-bridge-sampler/contracts/src/ApproximateBuys.sol b/packages/asset-swapper/contracts/src/ApproximateBuys.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/ApproximateBuys.sol rename to packages/asset-swapper/contracts/src/ApproximateBuys.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/CurveSampler.sol b/packages/asset-swapper/contracts/src/CurveSampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/CurveSampler.sol rename to packages/asset-swapper/contracts/src/CurveSampler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/DummyLiquidityProvider.sol b/packages/asset-swapper/contracts/src/DummyLiquidityProvider.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/DummyLiquidityProvider.sol rename to packages/asset-swapper/contracts/src/DummyLiquidityProvider.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/DummyLiquidityProviderRegistry.sol b/packages/asset-swapper/contracts/src/DummyLiquidityProviderRegistry.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/DummyLiquidityProviderRegistry.sol rename to packages/asset-swapper/contracts/src/DummyLiquidityProviderRegistry.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol b/packages/asset-swapper/contracts/src/ERC20BridgeSampler.sol similarity index 90% rename from contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol rename to packages/asset-swapper/contracts/src/ERC20BridgeSampler.sol index 7028238f61..fa201baec8 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol +++ b/packages/asset-swapper/contracts/src/ERC20BridgeSampler.sol @@ -24,20 +24,22 @@ import "./Eth2DaiSampler.sol"; import "./KyberSampler.sol"; import "./LiquidityProviderSampler.sol"; import "./MultiBridgeSampler.sol"; +import "./MStableSampler.sol"; import "./NativeOrderSampler.sol"; import "./UniswapSampler.sol"; import "./UniswapV2Sampler.sol"; contract ERC20BridgeSampler is - Eth2DaiSampler, - UniswapSampler, - KyberSampler, CurveSampler, + Eth2DaiSampler, + KyberSampler, LiquidityProviderSampler, - UniswapV2Sampler, + MStableSampler, MultiBridgeSampler, - NativeOrderSampler + NativeOrderSampler, + UniswapSampler, + UniswapV2Sampler { /// @dev Call multiple public functions on this contract in a single transaction. /// @param callDatas ABI-encoded call data for each function call. @@ -49,6 +51,9 @@ contract ERC20BridgeSampler is { callResults = new bytes[](callDatas.length); for (uint256 i = 0; i != callDatas.length; ++i) { + if (callDatas[i].length == 0) { + continue; + } (bool didSucceed, bytes memory resultData) = address(this).staticcall(callDatas[i]); if (!didSucceed) { assembly { revert(add(resultData, 0x20), mload(resultData)) } diff --git a/contracts/erc20-bridge-sampler/contracts/src/Eth2DaiSampler.sol b/packages/asset-swapper/contracts/src/Eth2DaiSampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/Eth2DaiSampler.sol rename to packages/asset-swapper/contracts/src/Eth2DaiSampler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/ICurve.sol b/packages/asset-swapper/contracts/src/ICurve.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/ICurve.sol rename to packages/asset-swapper/contracts/src/ICurve.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IEth2Dai.sol b/packages/asset-swapper/contracts/src/IEth2Dai.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IEth2Dai.sol rename to packages/asset-swapper/contracts/src/IEth2Dai.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IKyberHintHandler.sol b/packages/asset-swapper/contracts/src/IKyberHintHandler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IKyberHintHandler.sol rename to packages/asset-swapper/contracts/src/IKyberHintHandler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IKyberNetwork.sol b/packages/asset-swapper/contracts/src/IKyberNetwork.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IKyberNetwork.sol rename to packages/asset-swapper/contracts/src/IKyberNetwork.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IKyberNetworkProxy.sol b/packages/asset-swapper/contracts/src/IKyberNetworkProxy.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IKyberNetworkProxy.sol rename to packages/asset-swapper/contracts/src/IKyberNetworkProxy.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IKyberStorage.sol b/packages/asset-swapper/contracts/src/IKyberStorage.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IKyberStorage.sol rename to packages/asset-swapper/contracts/src/IKyberStorage.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/ILiquidityProvider.sol b/packages/asset-swapper/contracts/src/ILiquidityProvider.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/ILiquidityProvider.sol rename to packages/asset-swapper/contracts/src/ILiquidityProvider.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/ILiquidityProviderRegistry.sol b/packages/asset-swapper/contracts/src/ILiquidityProviderRegistry.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/ILiquidityProviderRegistry.sol rename to packages/asset-swapper/contracts/src/ILiquidityProviderRegistry.sol diff --git a/packages/asset-swapper/contracts/src/IMStable.sol b/packages/asset-swapper/contracts/src/IMStable.sol new file mode 100644 index 0000000000..ee2909d3ee --- /dev/null +++ b/packages/asset-swapper/contracts/src/IMStable.sol @@ -0,0 +1,32 @@ +/* + + 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; + + +interface IMStable { + + function getSwapOutput( + address _input, + address _output, + uint256 _quantity + ) + external + view + returns (bool, string memory, uint256 output); +} diff --git a/contracts/erc20-bridge-sampler/contracts/src/IMultiBridge.sol b/packages/asset-swapper/contracts/src/IMultiBridge.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IMultiBridge.sol rename to packages/asset-swapper/contracts/src/IMultiBridge.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IUniswapExchangeQuotes.sol b/packages/asset-swapper/contracts/src/IUniswapExchangeQuotes.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IUniswapExchangeQuotes.sol rename to packages/asset-swapper/contracts/src/IUniswapExchangeQuotes.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/IUniswapV2Router01.sol b/packages/asset-swapper/contracts/src/IUniswapV2Router01.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/IUniswapV2Router01.sol rename to packages/asset-swapper/contracts/src/IUniswapV2Router01.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/KyberSampler.sol b/packages/asset-swapper/contracts/src/KyberSampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/KyberSampler.sol rename to packages/asset-swapper/contracts/src/KyberSampler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/LiquidityProviderSampler.sol b/packages/asset-swapper/contracts/src/LiquidityProviderSampler.sol similarity index 98% rename from contracts/erc20-bridge-sampler/contracts/src/LiquidityProviderSampler.sol rename to packages/asset-swapper/contracts/src/LiquidityProviderSampler.sol index b10b5912b0..2838787e70 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/LiquidityProviderSampler.sol +++ b/packages/asset-swapper/contracts/src/LiquidityProviderSampler.sol @@ -127,6 +127,9 @@ contract LiquidityProviderSampler is view returns (address providerAddress) { + if (registryAddress == address(0)) { + return address(0); + } bytes memory callData = abi.encodeWithSelector( ILiquidityProviderRegistry(0).getLiquidityProviderForMarket.selector, takerToken, diff --git a/packages/asset-swapper/contracts/src/MStableSampler.sol b/packages/asset-swapper/contracts/src/MStableSampler.sol new file mode 100644 index 0000000000..ae6c4767e5 --- /dev/null +++ b/packages/asset-swapper/contracts/src/MStableSampler.sol @@ -0,0 +1,126 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; +import "@0x/contracts-utils/contracts/src/LibBytes.sol"; +import "./IMStable.sol"; +import "./ApproximateBuys.sol"; +import "./SamplerUtils.sol"; + + +contract MStableSampler is + DeploymentConstants, + SamplerUtils, + ApproximateBuys +{ + /// @dev Default gas limit for mStable calls. + uint256 constant private DEFAULT_CALL_GAS = 800e3; // 800k + + /// @dev Sample sell quotes from the mStable mUSD contract + /// @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 makerTokenAmounts Maker amounts bought at each taker token + /// amount. + function sampleSellsFromMStable( + address takerToken, + address makerToken, + uint256[] memory takerTokenAmounts + ) + public + view + returns (uint256[] memory makerTokenAmounts) + { + // Initialize array of maker token amounts. + uint256 numSamples = takerTokenAmounts.length; + 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)); + } else { + break; + } + makerTokenAmounts[i] = buyAmount; + } + } + + /// @dev Sample buy quotes from MStable mUSD contract + /// @param takerToken Address of the taker token (what to sell). + /// @param makerToken Address of the maker token (what to buy). + /// @param makerTokenAmounts Maker token buy amount for each sample. + /// @return takerTokenAmounts Taker amounts sold at each maker token + /// amount. + function sampleBuysFromMStable( + address takerToken, + address makerToken, + uint256[] memory makerTokenAmounts + ) + public + view + returns (uint256[] memory takerTokenAmounts) + { + return _sampleApproximateBuys( + ApproximateBuyQuoteOpts({ + makerTokenData: abi.encode(makerToken), + takerTokenData: abi.encode(takerToken), + getSellQuoteCallback: _sampleSellForApproximateBuyFromMStable + }), + makerTokenAmounts + ); + } + + function _sampleSellForApproximateBuyFromMStable( + bytes memory takerTokenData, + bytes memory makerTokenData, + uint256 sellAmount + ) + private + view + returns (uint256 buyAmount) + { + (address takerToken) = + 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) { + return 0; + } + // solhint-disable-next-line indent + return abi.decode(resultData, (uint256[]))[0]; + } +} diff --git a/contracts/erc20-bridge-sampler/contracts/src/MultiBridgeSampler.sol b/packages/asset-swapper/contracts/src/MultiBridgeSampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/MultiBridgeSampler.sol rename to packages/asset-swapper/contracts/src/MultiBridgeSampler.sol diff --git a/packages/asset-swapper/contracts/src/NativeOrderSampler.sol b/packages/asset-swapper/contracts/src/NativeOrderSampler.sol new file mode 100644 index 0000000000..3ba797906b --- /dev/null +++ b/packages/asset-swapper/contracts/src/NativeOrderSampler.sol @@ -0,0 +1,205 @@ +/* + + 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-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"; + + +contract NativeOrderSampler { + using LibSafeMath for uint256; + using LibBytes for bytes; + + /// @dev The Exchange ERC20Proxy ID. + bytes4 private constant ERC20_ASSET_PROXY_ID = 0xf47261b0; + /// @dev Gas limit for calls to `getOrderFillableTakerAmount()`. + uint256 constant internal DEFAULT_CALL_GAS = 200e3; // 200k + + /// @dev Queries the fillable taker asset amounts of native orders. + /// Effectively ignores orders that have empty signatures or + /// maker/taker asset amounts (returning 0). + /// @param orders Native orders to query. + /// @param orderSignatures Signatures for each respective order in `orders`. + /// @param exchange The V3 exchange. + /// @return orderFillableTakerAssetAmounts How much taker asset can be filled + /// by each order in `orders`. + function getOrderFillableTakerAssetAmounts( + LibOrder.Order[] memory orders, + bytes[] memory orderSignatures, + IExchange exchange + ) + public + view + returns (uint256[] memory orderFillableTakerAssetAmounts) + { + 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, + orders[i], + orderSignatures[i], + exchange + )); + // solhint-enable indent + orderFillableTakerAssetAmounts[i] = didSucceed + ? abi.decode(resultData, (uint256)) + : 0; + } + } + + /// @dev Queries the fillable taker asset amounts of native orders. + /// Effectively ignores orders that have empty signatures or + /// @param orders Native orders to query. + /// @param orderSignatures Signatures for each respective order in `orders`. + /// @param exchange The V3 exchange. + /// @return orderFillableMakerAssetAmounts How much maker asset can be filled + /// by each order in `orders`. + function getOrderFillableMakerAssetAmounts( + LibOrder.Order[] memory orders, + bytes[] memory orderSignatures, + IExchange exchange + ) + public + view + returns (uint256[] memory orderFillableMakerAssetAmounts) + { + orderFillableMakerAssetAmounts = getOrderFillableTakerAssetAmounts( + orders, + orderSignatures, + exchange + ); + // `orderFillableMakerAssetAmounts` now holds taker asset amounts, so + // convert them to maker asset amounts. + for (uint256 i = 0; i < orders.length; ++i) { + if (orderFillableMakerAssetAmounts[i] != 0) { + orderFillableMakerAssetAmounts[i] = LibMath.getPartialAmountCeil( + orderFillableMakerAssetAmounts[i], + orders[i].takerAssetAmount, + orders[i].makerAssetAmount + ); + } + } + } + + /// @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, + bytes memory signature, + IExchange exchange + ) + public + view + returns (uint256 fillableTakerAmount) + { + if (signature.length == 0 || + order.makerAssetAmount == 0 || + order.takerAssetAmount == 0) + { + return 0; + } + + LibOrder.OrderInfo memory orderInfo = exchange.getOrderInfo(order); + if (orderInfo.orderStatus != LibOrder.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)) { + return 0; + } + IERC20Token makerFeeToken = order.makerFee > 0 + ? _getTokenFromERC20AssetData(order.makerFeeAssetData) + : IERC20Token(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( + remainingTakerAmount, + order.takerAssetAmount, + makerFeeToken == makerToken + ? order.makerAssetAmount.safeAdd(order.makerFee) + : order.makerAssetAmount + ); + // 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( + 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( + spendableMakerAmount, + totalFillableMakerAmount, + remainingTakerAmount + ); + } + // 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( + makerFeeToken.balanceOf(order.makerAddress), + makerFeeToken.allowance(order.makerAddress, spender) + ); + if (spendableExtraMakerFeeAmount < order.makerFee) { + fillableTakerAmount = LibSafeMath.min256( + fillableTakerAmount, + LibMath.getPartialAmountCeil( + spendableExtraMakerFeeAmount, + order.makerFee, + remainingTakerAmount + ) + ); + } + } + } + + function _getTokenFromERC20AssetData(bytes memory assetData) + private + pure + returns (IERC20Token token) + { + if (assetData.length == 0) { + return IERC20Token(address(0)); + } + if (assetData.length != 36 || + assetData.readBytes4(0) != ERC20_ASSET_PROXY_ID) + { + return IERC20Token(address(0)); + } + return IERC20Token(assetData.readAddress(16)); + } +} diff --git a/contracts/erc20-bridge-sampler/contracts/src/SamplerUtils.sol b/packages/asset-swapper/contracts/src/SamplerUtils.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/SamplerUtils.sol rename to packages/asset-swapper/contracts/src/SamplerUtils.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/UniswapSampler.sol b/packages/asset-swapper/contracts/src/UniswapSampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/UniswapSampler.sol rename to packages/asset-swapper/contracts/src/UniswapSampler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/src/UniswapV2Sampler.sol b/packages/asset-swapper/contracts/src/UniswapV2Sampler.sol similarity index 100% rename from contracts/erc20-bridge-sampler/contracts/src/UniswapV2Sampler.sol rename to packages/asset-swapper/contracts/src/UniswapV2Sampler.sol diff --git a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol b/packages/asset-swapper/contracts/test/TestERC20BridgeSampler.sol similarity index 93% rename from contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol rename to packages/asset-swapper/contracts/test/TestERC20BridgeSampler.sol index 4ff95bf126..64b58411f3 100644 --- a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol +++ b/packages/asset-swapper/contracts/test/TestERC20BridgeSampler.sol @@ -23,7 +23,6 @@ import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "../src/ERC20BridgeSampler.sol"; import "../src/IEth2Dai.sol"; -import "../src/IDevUtils.sol"; import "../src/IKyberNetworkProxy.sol"; import "../src/IUniswapV2Router01.sol"; @@ -477,33 +476,17 @@ contract TestERC20BridgeSampler is uniswap.createTokenExchanges(tokenAddresses); } - // `IDevUtils.getOrderRelevantState()`, overridden to return deterministic - // states. - function getOrderRelevantState( + // Overridden to return deterministic states. + function getOrderFillableTakerAmount( LibOrder.Order memory order, - bytes memory + bytes memory, + IExchange ) public - pure - returns ( - LibOrder.OrderInfo memory orderInfo, - uint256 fillableTakerAssetAmount, - bool isValidSignature - ) + view + returns (uint256 fillableTakerAmount) { - // The order hash is just the hash of the salt. - bytes32 orderHash = keccak256(abi.encode(order.salt)); - // Everything else is derived from the hash. - orderInfo.orderHash = orderHash; - if (uint256(orderHash) % 100 > 90) { - orderInfo.orderStatus = LibOrder.OrderStatus.FULLY_FILLED; - } else { - orderInfo.orderStatus = LibOrder.OrderStatus.FILLABLE; - } - orderInfo.orderTakerAssetFilledAmount = uint256(orderHash) % order.takerAssetAmount; - fillableTakerAssetAmount = - order.takerAssetAmount - orderInfo.orderTakerAssetFilledAmount; - isValidSignature = uint256(orderHash) % 2 == 1; + return uint256(keccak256(abi.encode(order.salt))) % order.takerAssetAmount; } // Overriden to return deterministic decimals. diff --git a/packages/asset-swapper/contracts/test/TestNativeOrderSampler.sol b/packages/asset-swapper/contracts/test/TestNativeOrderSampler.sol new file mode 100644 index 0000000000..90b23e9d94 --- /dev/null +++ b/packages/asset-swapper/contracts/test/TestNativeOrderSampler.sol @@ -0,0 +1,109 @@ +/* + + 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-exchange/contracts/src/interfaces/IExchange.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; +import "../src/NativeOrderSampler.sol"; + + +contract TestNativeOrderSamplerToken { + mapping (address => uint256) public balanceOf; + mapping (address => mapping(address => uint256)) public allowance; + + function setBalanceAndAllowance( + address owner, + address spender, + uint256 balance, + uint256 allowance_ + ) + external + { + balanceOf[owner] = balance; + allowance[owner][spender] = allowance_; + } +} + +contract TestNativeOrderSampler is + NativeOrderSampler +{ + uint8 private constant MAX_ORDER_STATUS = uint8(LibOrder.OrderStatus.CANCELLED) + 1; + bytes32 private constant VALID_SIGNATURE_HASH = keccak256(hex"01"); + + function createTokens(uint256 count) + external + returns (TestNativeOrderSamplerToken[] memory tokens) + { + tokens = new TestNativeOrderSamplerToken[](count); + for (uint256 i = 0; i < count; ++i) { + tokens[i] = new TestNativeOrderSamplerToken(); + } + } + + function setTokenBalanceAndAllowance( + TestNativeOrderSamplerToken token, + address owner, + address spender, + uint256 balance, + uint256 allowance + ) + external + { + token.setBalanceAndAllowance(owner, spender, balance, allowance); + } + + // IExchange.getAssetProxy() + function getAssetProxy(bytes4 proxyId) + public + pure + returns (address) + { + return address(uint160(uint256(keccak256(abi.encode(proxyId))))); + } + + // IExchange.getOrderInfo() + function getOrderInfo(LibOrder.Order calldata order) + external + pure + returns (LibOrder.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; + } else { + orderInfo.orderStatus = LibOrder.OrderStatus.FILLABLE; + } + // The expiration time is the filled taker asset amount. + orderInfo.orderTakerAssetFilledAmount = order.expirationTimeSeconds; + } + + // IExchange.isValidSignature() + function isValidHashSignature( + bytes32, + address, + bytes calldata signature + ) + external + pure + returns (bool isValid) + { + return keccak256(signature) == VALID_SIGNATURE_HASH; + } +} diff --git a/packages/asset-swapper/package.json b/packages/asset-swapper/package.json index 3e2e444a2e..1654119a4c 100644 --- a/packages/asset-swapper/package.json +++ b/packages/asset-swapper/package.json @@ -8,26 +8,35 @@ "main": "lib/src/index.js", "types": "lib/src/index.d.ts", "scripts": { - "build": "yarn tsc -b", + "build": "yarn pre_build && tsc -b", "watch": "tsc -w -p tsconfig.json", "build:ci": "yarn build", - "lint": "tslint --format stylish --project . && yarn prettier --check", + "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy", + "compile": "sol-compiler", + "lint": "tslint --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./test/generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", + "lint-contracts": "#solhint -c .solhint.json contracts/**/**/**/**/*.sol", "prettier": "prettier '**/*.{ts,tsx,json,md}' --config ../../.prettierrc --ignore-path ../../.prettierignore", - "fix": "tslint --fix --format stylish --project . && yarn prettier --write", + "fix": "tslint --fix --format stylish --project . --exclude ./generated-wrappers/**/* --exclude ./generated-artifacts/**/* --exclude ./test/generated-wrappers/**/* --exclude ./test/generated-artifacts/**/* --exclude **/lib/**/* && yarn lint-contracts", "test": "yarn run_mocha", "rebuild_and_test": "run-s clean build test", "test:coverage": "nyc npm run test --all && yarn coverage:report:lcov", "coverage:report:lcov": "nyc report --reporter=text-lcov > coverage/lcov.info", "test:circleci": "yarn test:coverage", - "run_mocha": "mocha --require source-map-support/register --require make-promises-safe lib/test/**/*_test.js lib/test/global_hooks.js --timeout 30000 --bail --exit", - "clean": "shx rm -rf lib test_temp generated_docs", + "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*_test.js' lib/test/global_hooks.js --timeout 30000 --bail --exit", + "clean": "shx rm -rf lib test_temp generated_docs test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers", "diff_docs": "git diff --exit-code ./docs", "s3:sync_md_docs": "aws s3 sync ./docs s3://docs-markdown/${npm_package_name}/v${npm_package_version} --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", "docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json", "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES", + "generate_contract_wrappers": "abi-gen --debug --abis ${npm_package_config_abis} --output test/generated-wrappers --backend ethers", + "contracts:gen": "contracts-gen generate", + "contracts:copy": "contracts-gen copy", "publish:private": "yarn build && gitpkg publish" }, "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|CurveSampler|DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|Eth2DaiSampler|ICurve|IEth2Dai|IKyberHintHandler|IKyberNetwork|IKyberNetworkProxy|IKyberStorage|ILiquidityProvider|ILiquidityProviderRegistry|IMStable|IMultiBridge|IUniswapExchangeQuotes|IUniswapV2Router01|KyberSampler|LiquidityProviderSampler|MStableSampler|MultiBridgeSampler|NativeOrderSampler|SamplerUtils|TestERC20BridgeSampler|TestNativeOrderSampler|UniswapSampler|UniswapV2Sampler).json", "postpublish": { "assets": [] } @@ -47,34 +56,43 @@ }, "dependencies": { "@0x/assert": "^3.0.9", + "@0x/base-contract": "^6.2.3", "@0x/contract-addresses": "^4.11.0", - "@0x/contract-artifacts": "^3.7.1", "@0x/contract-wrappers": "^13.8.0", "@0x/json-schemas": "^5.1.0", "@0x/order-utils": "^10.3.0", "@0x/orderbook": "^2.2.7", "@0x/quote-server": "^2.0.2", + "@0x/types": "^3.2.0", + "@0x/typescript-typings": "^5.1.1", "@0x/utils": "^5.5.1", "@0x/web3-wrapper": "^7.2.0", "@balancer-labs/sor": "0.3.2", "axios": "^0.19.2", "axios-mock-adapter": "^1.18.1", "decimal.js": "^10.2.0", + "ethereum-types": "^3.2.0", "ethereumjs-util": "^5.1.1", "heartbeats": "^5.0.1", "lodash": "^4.17.11" }, "devDependencies": { "@0x/base-contract": "^6.2.3", + "@0x/contracts-asset-proxy": "^3.4.0", + "@0x/contracts-erc20": "^3.2.1", + "@0x/contracts-exchange": "^3.2.7", + "@0x/contracts-exchange-libs": "^4.3.7", + "@0x/contracts-gen": "^2.0.10", "@0x/contracts-test-utils": "^5.3.4", + "@0x/contracts-utils": "^4.5.1", "@0x/dev-utils": "^3.3.0", "@0x/mesh-rpc-client": "^7.0.4-beta-0xv3", "@0x/migrations": "^6.4.0", + "@0x/sol-compiler": "^4.1.1", "@0x/subproviders": "^6.1.1", "@0x/ts-doc-gen": "^0.0.22", "@0x/tslint-config": "^4.1.0", "@0x/types": "^3.2.0", - "@0x/typescript-typings": "^5.1.1", "@types/lodash": "4.14.104", "@types/mocha": "^5.2.7", "@types/node": "*", @@ -82,7 +100,6 @@ "chai-as-promised": "^7.1.0", "chai-bignumber": "^3.0.0", "dirty-chai": "^2.0.1", - "ethereum-types": "^3.2.0", "gitpkg": "https://github.com/0xProject/gitpkg.git", "make-promises-safe": "^1.1.0", "mocha": "^6.2.0", diff --git a/contracts/erc20-bridge-sampler/src/artifacts.ts b/packages/asset-swapper/src/artifacts.ts similarity index 100% rename from contracts/erc20-bridge-sampler/src/artifacts.ts rename to packages/asset-swapper/src/artifacts.ts diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts index 698e294d39..4012a53bff 100644 --- a/packages/asset-swapper/src/index.ts +++ b/packages/asset-swapper/src/index.ts @@ -13,21 +13,57 @@ export { SRAWebsocketOrderProviderOpts, } from '@0x/orderbook'; export { RFQTFirmQuote, RFQTIndicativeQuote } from '@0x/quote-server'; -export { APIOrder, Asset, AssetPairsItem, SignedOrder } from '@0x/types'; -export { BigNumber } from '@0x/utils'; export { + APIOrder, + Asset, + AssetPairsItem, + DecodedLogEvent, + EventCallback, + IndexedFilterValues, + SignedOrder, +} from '@0x/types'; +export { BigNumber } from '@0x/utils'; +export { AxiosInstance } from 'axios'; +export { + AbiDefinition, BlockParam, BlockParamLiteral, + CompilerOpts, + CompilerSettings, + CompilerSettingsMetadata, + ConstructorAbi, + ConstructorStateMutability, + ContractAbi, + ContractArtifact, + ContractChainData, + ContractChains, + ContractEventArg, DataItem, + DecodedLogArgs, + DevdocOutput, EIP1193Event, EIP1193Provider, + EventAbi, EventParameter, + EvmBytecodeOutput, + EvmBytecodeOutputLinkReferences, + EvmOutput, + FallbackAbi, + FunctionAbi, GanacheProvider, GethCallOverrides, JSONRPCErrorCallback, JSONRPCRequestPayload, JSONRPCResponseError, JSONRPCResponsePayload, + LogWithDecodedArgs, + MethodAbi, + OptimizerSettings, + OutputField, + ParamDescription, + RevertErrorAbi, + StandardContractOutput, + StateMutability, SupportedProvider, TupleDataItem, Web3JsProvider, @@ -36,6 +72,7 @@ export { Web3JsV3Provider, ZeroExProvider, } from 'ethereum-types'; +export { artifacts } from './artifacts'; export { InsufficientAssetLiquidityError } from './errors'; export { SwapQuoteConsumer } from './quote_consumers/swap_quote_consumer'; export { SwapQuoter } from './swap_quoter'; @@ -99,7 +136,6 @@ export { } from './utils/quote_report_generator'; export { QuoteRequestor } from './utils/quote_requestor'; export { rfqtMocker } from './utils/rfqt_mocker'; +export { ERC20BridgeSamplerContract } from './wrappers'; import { ERC20BridgeSource } from './utils/market_operation_utils/types'; export type Native = ERC20BridgeSource.Native; - -export { AxiosInstance } from 'axios'; diff --git a/packages/asset-swapper/src/swap_quoter.ts b/packages/asset-swapper/src/swap_quoter.ts index 08d9ab83f3..333fef93e5 100644 --- a/packages/asset-swapper/src/swap_quoter.ts +++ b/packages/asset-swapper/src/swap_quoter.ts @@ -1,6 +1,5 @@ import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses'; -import { ERC20BridgeSampler } from '@0x/contract-artifacts'; -import { DevUtilsContract, ERC20BridgeSamplerContract } from '@0x/contract-wrappers'; +import { DevUtilsContract } from '@0x/contract-wrappers'; import { schemas } from '@0x/json-schemas'; import { assetDataUtils, SignedOrder } from '@0x/order-utils'; import { MeshOrderProviderOpts, Orderbook, SRAPollingOrderProviderOpts } from '@0x/orderbook'; @@ -8,6 +7,7 @@ import { BigNumber, providerUtils } from '@0x/utils'; import { BlockParamLiteral, SupportedProvider, ZeroExProvider } from 'ethereum-types'; import * as _ from 'lodash'; +import { artifacts } from './artifacts'; import { constants } from './constants'; import { CalculateSwapQuoteOpts, @@ -39,6 +39,7 @@ import { ProtocolFeeUtils } from './utils/protocol_fee_utils'; import { QuoteRequestor } from './utils/quote_requestor'; import { sortingUtils } from './utils/sorting_utils'; import { SwapQuoteCalculator } from './utils/swap_quote_calculator'; +import { ERC20BridgeSamplerContract } from './wrappers'; export class SwapQuoter { public readonly provider: ZeroExProvider; @@ -183,7 +184,7 @@ export class SwapQuoter { ); this._orderStateUtils = new OrderStateUtils(this._devUtilsContract); // Allow the sampler bytecode to be overwritten using geths override functionality - const samplerBytecode = _.get(ERC20BridgeSampler, 'compilerOutput.evm.deployedBytecode.object'); + const samplerBytecode = _.get(artifacts.ERC20BridgeSampler, 'compilerOutput.evm.deployedBytecode.object'); const defaultCodeOverrides = samplerBytecode ? { [this._contractAddresses.erc20BridgeSampler]: { code: samplerBytecode }, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index f454560b4c..8a98b6acba 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -14,6 +14,7 @@ export const SELL_SOURCES = [ ERC20BridgeSource.Kyber, ERC20BridgeSource.Curve, ERC20BridgeSource.Balancer, + ERC20BridgeSource.MStable, ]; /** @@ -26,6 +27,7 @@ export const BUY_SOURCES = [ ERC20BridgeSource.Kyber, ERC20BridgeSource.Curve, ERC20BridgeSource.Balancer, + ERC20BridgeSource.MStable, ]; export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = { diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 85bfef8633..1fae744529 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -97,7 +97,7 @@ export class MarketOperationUtils { // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( // Get native order fillable amounts. - DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.devUtils), + DexOrderSampler.ops.getOrderFillableTakerAmounts(nativeOrders, this.contractAddresses.exchange), // Get the custom liquidity provider from registry. DexOrderSampler.ops.getLiquidityProviderFromRegistry( this._liquidityProviderRegistry, @@ -213,7 +213,7 @@ export class MarketOperationUtils { // Call the sampler contract. const samplerPromise = this._sampler.executeAsync( // Get native order fillable amounts. - DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.devUtils), + DexOrderSampler.ops.getOrderFillableMakerAmounts(nativeOrders, this.contractAddresses.exchange), // Get the custom liquidity provider from registry. DexOrderSampler.ops.getLiquidityProviderFromRegistry( this._liquidityProviderRegistry, @@ -381,7 +381,7 @@ export class MarketOperationUtils { const sources = difference(BUY_SOURCES, _opts.excludedSources); const ops = [ ...batchNativeOrders.map(orders => - DexOrderSampler.ops.getOrderFillableMakerAmounts(orders, this.contractAddresses.devUtils), + DexOrderSampler.ops.getOrderFillableMakerAmounts(orders, this.contractAddresses.exchange), ), ...(await Promise.all( batchNativeOrders.map(async orders => diff --git a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts index f07a61a0a7..2e639c9ef3 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/orders.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/orders.ts @@ -196,6 +196,8 @@ function getBridgeAddressFromFill(fill: CollapsedFill, opts: CreateOrderFromPath return (fill.fillData as LiquidityProviderFillData).poolAddress; case ERC20BridgeSource.MultiBridge: return (fill.fillData as MultiBridgeFillData).poolAddress; + case ERC20BridgeSource.MStable: + return opts.contractAddresses.mStableBridge; default: break; } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts index e1fa6d8fe7..f9855cc22d 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts @@ -1,7 +1,7 @@ -import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers'; -import { BigNumber } from '@0x/utils'; +import { BigNumber, NULL_BYTES } from '@0x/utils'; import { SamplerOverrides } from '../../types'; +import { ERC20BridgeSamplerContract } from '../../wrappers'; import { BalancerPoolsCache } from './balancer_utils'; import { samplerOperations } from './sampler_operations'; @@ -144,18 +144,23 @@ export class DexOrderSampler { const { overrides, block } = this._samplerOverrides ? this._samplerOverrides : { overrides: undefined, block: undefined }; + + // All operations are NOOPs + if (callDatas.every(cd => cd === NULL_BYTES)) { + return Promise.all( + callDatas.map(async (_callData, i) => ops[i].handleCallResultsAsync(this._samplerContract, NULL_BYTES)), + ); + } // Execute all non-empty calldatas. const rawCallResults = await this._samplerContract - .batchCall(callDatas.filter(cd => cd !== '0x')) + .batchCall(callDatas.filter(cd => cd !== NULL_BYTES)) .callAsync({ overrides }, block); // Return the parsed results. let rawCallResultsIdx = 0; return Promise.all( callDatas.map(async (callData, i) => { - if (callData !== '0x') { - return ops[i].handleCallResultsAsync(this._samplerContract, rawCallResults[rawCallResultsIdx++]); - } - return ops[i].handleCallResultsAsync(this._samplerContract, '0x'); + const result = callData !== NULL_BYTES ? rawCallResults[rawCallResultsIdx++] : NULL_BYTES; + return ops[i].handleCallResultsAsync(this._samplerContract, result); }), ); } diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts index 4090914a83..c48424984e 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler_operations.ts @@ -3,6 +3,7 @@ import * as _ from 'lodash'; import { BigNumber, ERC20BridgeSource, SignedOrder } from '../..'; import { BalancerPool, BalancerPoolsCache, computeBalancerBuyQuote, computeBalancerSellQuote } from './balancer_utils'; +import { NULL_BYTES, ZERO_AMOUNT } from './constants'; import { getCurveInfosForPair } from './curve_utils'; import { getMultiBridgeIntermediateToken } from './multibridge_utils'; import { @@ -20,11 +21,11 @@ import { * for use with `DexOrderSampler.executeAsync()`. */ export const samplerOperations = { - getOrderFillableTakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation { + getOrderFillableTakerAmounts(orders: SignedOrder[], exchangeAddress: string): BatchedOperation { return { encodeCall: contract => { return contract - .getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress) + .getOrderFillableTakerAssetAmounts(orders, orders.map(o => o.signature), exchangeAddress) .getABIEncodedTransactionData(); }, handleCallResultsAsync: async (contract, callResults) => { @@ -32,11 +33,11 @@ export const samplerOperations = { }, }; }, - getOrderFillableMakerAmounts(orders: SignedOrder[], devUtilsAddress: string): BatchedOperation { + getOrderFillableMakerAmounts(orders: SignedOrder[], exchangeAddress: string): BatchedOperation { return { encodeCall: contract => { return contract - .getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature), devUtilsAddress) + .getOrderFillableMakerAssetAmounts(orders, orders.map(o => o.signature), exchangeAddress) .getABIEncodedTransactionData(); }, handleCallResultsAsync: async (contract, callResults) => { @@ -301,6 +302,32 @@ export const samplerOperations = { ...samplerOperations.constant(makerFillAmounts.map(amount => computeBalancerBuyQuote(pool, amount))), }; }, + getMStableSellQuotes(makerToken: string, takerToken: string, takerFillAmounts: BigNumber[]): SourceQuoteOperation { + return { + source: ERC20BridgeSource.MStable, + encodeCall: contract => { + return contract + .sampleSellsFromMStable(makerToken, takerToken, takerFillAmounts) + .getABIEncodedTransactionData(); + }, + handleCallResultsAsync: async (contract, callResults) => { + return contract.getABIDecodedReturnData('sampleSellsFromMStable', callResults); + }, + }; + }, + getMStableBuyQuotes(makerToken: string, takerToken: string, makerFillAmounts: BigNumber[]): SourceQuoteOperation { + return { + source: ERC20BridgeSource.MStable, + encodeCall: contract => { + return contract + .sampleBuysFromMStable(makerToken, takerToken, makerFillAmounts) + .getABIEncodedTransactionData(); + }, + handleCallResultsAsync: async (contract, callResults) => { + return contract.getABIDecodedReturnData('sampleBuysFromMStable', callResults); + }, + }; + }, getMedianSellRateAsync: async ( sources: ERC20BridgeSource[], makerToken: string, @@ -326,21 +353,29 @@ export const samplerOperations = { ); return { encodeCall: contract => { + const encodedCall = getSellQuotes.encodeCall(contract); + // All soures were excluded + if (encodedCall === NULL_BYTES) { + return NULL_BYTES; + } const subCalls = [getSellQuotes.encodeCall(contract)]; return contract.batchCall(subCalls).getABIEncodedTransactionData(); }, handleCallResultsAsync: async (contract, callResults) => { + if (callResults === NULL_BYTES) { + return ZERO_AMOUNT; + } const rawSubCallResults = contract.getABIDecodedReturnData('batchCall', callResults); const samples = await getSellQuotes.handleCallResultsAsync(contract, rawSubCallResults[0]); if (samples.length === 0) { - return new BigNumber(0); + return ZERO_AMOUNT; } const flatSortedSamples = samples .reduce((acc, v) => acc.concat(...v)) .filter(v => !v.output.isZero()) .sort((a, b) => a.output.comparedTo(b.output)); if (flatSortedSamples.length === 0) { - return new BigNumber(0); + return ZERO_AMOUNT; } const medianSample = flatSortedSamples[Math.floor(flatSortedSamples.length / 2)]; return medianSample.output.div(medianSample.input); @@ -350,7 +385,7 @@ export const samplerOperations = { constant(result: T): BatchedOperation { return { encodeCall: _contract => { - return '0x'; + return NULL_BYTES; }, handleCallResultsAsync: async (_contract, _callResults) => { return result; @@ -456,6 +491,8 @@ export const samplerOperations = { return pools.map(pool => samplerOperations.getBalancerSellQuotes(pool, takerFillAmounts), ); + case ERC20BridgeSource.MStable: + return samplerOperations.getMStableSellQuotes(makerToken, takerToken, takerFillAmounts); default: throw new Error(`Unsupported sell sample source: ${source}`); } @@ -467,17 +504,27 @@ export const samplerOperations = { const nonSamplerOps = subOps.filter(op => op.source === ERC20BridgeSource.Balancer); return { encodeCall: contract => { + // All operations are NOOPs + if (samplerOps.length === 0) { + return NULL_BYTES; + } const subCalls = samplerOps.map(op => op.encodeCall(contract)); return contract.batchCall(subCalls).getABIEncodedTransactionData(); }, handleCallResultsAsync: async (contract, callResults) => { - const rawSubCallResults = contract.getABIDecodedReturnData('batchCall', callResults); - let samples = await Promise.all( - samplerOps.map(async (op, i) => op.handleCallResultsAsync(contract, rawSubCallResults[i])), - ); - samples = samples.concat( - await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))), - ); + let samples: BigNumber[][]; + // If all operations were NOOPs then just call the handle result callback + if (callResults === NULL_BYTES && samplerOps.length === 0) { + samples = await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))); + } else { + const rawSubCallResults = contract.getABIDecodedReturnData('batchCall', callResults); + samples = await Promise.all( + samplerOps.map(async (op, i) => op.handleCallResultsAsync(contract, rawSubCallResults[i])), + ); + samples = samples.concat( + await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))), + ); + } return [...samplerOps, ...nonSamplerOps].map((op, i) => { return samples[i].map((output, j) => ({ source: op.source, @@ -553,6 +600,8 @@ export const samplerOperations = { return pools.map(pool => samplerOperations.getBalancerBuyQuotes(pool, makerFillAmounts), ); + case ERC20BridgeSource.MStable: + return samplerOperations.getMStableBuyQuotes(makerToken, takerToken, makerFillAmounts); default: throw new Error(`Unsupported buy sample source: ${source}`); } @@ -564,17 +613,26 @@ export const samplerOperations = { const nonSamplerOps = subOps.filter(op => op.source === ERC20BridgeSource.Balancer); return { encodeCall: contract => { + // All operations are NOOPs + if (samplerOps.length === 0) { + return NULL_BYTES; + } const subCalls = samplerOps.map(op => op.encodeCall(contract)); return contract.batchCall(subCalls).getABIEncodedTransactionData(); }, handleCallResultsAsync: async (contract, callResults) => { - const rawSubCallResults = contract.getABIDecodedReturnData('batchCall', callResults); - let samples = await Promise.all( - samplerOps.map(async (op, i) => op.handleCallResultsAsync(contract, rawSubCallResults[i])), - ); - samples = samples.concat( - await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))), - ); + let samples: BigNumber[][]; + if (callResults === NULL_BYTES && samplerOps.length === 0) { + samples = await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))); + } else { + const rawSubCallResults = contract.getABIDecodedReturnData('batchCall', callResults); + samples = await Promise.all( + samplerOps.map(async (op, i) => op.handleCallResultsAsync(contract, rawSubCallResults[i])), + ); + samples = samples.concat( + await Promise.all(nonSamplerOps.map(async op => op.handleCallResultsAsync(contract, ''))), + ); + } return [...samplerOps, ...nonSamplerOps].map((op, i) => { return samples[i].map((output, j) => ({ source: op.source, diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index 1f2c500ac9..5ad501693b 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -1,10 +1,10 @@ -import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { RFQTIndicativeQuote } from '@0x/quote-server'; import { MarketOperation, SignedOrder } from '@0x/types'; import { BigNumber } from '@0x/utils'; import { RfqtRequestOpts, SignedOrderWithFillableAmounts } from '../../types'; import { QuoteRequestor } from '../../utils/quote_requestor'; +import { ERC20BridgeSamplerContract } from '../../wrappers'; import { QuoteReport } from '../quote_report_generator'; /** @@ -38,6 +38,7 @@ export enum ERC20BridgeSource { LiquidityProvider = 'LiquidityProvider', MultiBridge = 'MultiBridge', Balancer = 'Balancer', + MStable = 'mStable', } // tslint:disable: enum-naming diff --git a/contracts/erc20-bridge-sampler/src/wrappers.ts b/packages/asset-swapper/src/wrappers.ts similarity index 100% rename from contracts/erc20-bridge-sampler/src/wrappers.ts rename to packages/asset-swapper/src/wrappers.ts diff --git a/contracts/erc20-bridge-sampler/test/artifacts.ts b/packages/asset-swapper/test/artifacts.ts similarity index 90% rename from contracts/erc20-bridge-sampler/test/artifacts.ts rename to packages/asset-swapper/test/artifacts.ts index 378361abeb..3d1c893c7b 100644 --- a/contracts/erc20-bridge-sampler/test/artifacts.ts +++ b/packages/asset-swapper/test/artifacts.ts @@ -12,7 +12,6 @@ import * as DummyLiquidityProviderRegistry from '../test/generated-artifacts/Dum import * as ERC20BridgeSampler from '../test/generated-artifacts/ERC20BridgeSampler.json'; import * as Eth2DaiSampler from '../test/generated-artifacts/Eth2DaiSampler.json'; import * as ICurve from '../test/generated-artifacts/ICurve.json'; -import * as IDevUtils from '../test/generated-artifacts/IDevUtils.json'; import * as IEth2Dai from '../test/generated-artifacts/IEth2Dai.json'; import * as IKyberHintHandler from '../test/generated-artifacts/IKyberHintHandler.json'; import * as IKyberNetwork from '../test/generated-artifacts/IKyberNetwork.json'; @@ -20,15 +19,18 @@ import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkPr import * as IKyberStorage from '../test/generated-artifacts/IKyberStorage.json'; import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json'; import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json'; +import * as IMStable from '../test/generated-artifacts/IMStable.json'; import * as IMultiBridge from '../test/generated-artifacts/IMultiBridge.json'; import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json'; import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json'; import * as KyberSampler from '../test/generated-artifacts/KyberSampler.json'; import * as LiquidityProviderSampler from '../test/generated-artifacts/LiquidityProviderSampler.json'; +import * as MStableSampler from '../test/generated-artifacts/MStableSampler.json'; import * as MultiBridgeSampler from '../test/generated-artifacts/MultiBridgeSampler.json'; import * as NativeOrderSampler from '../test/generated-artifacts/NativeOrderSampler.json'; import * as SamplerUtils from '../test/generated-artifacts/SamplerUtils.json'; import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json'; +import * as TestNativeOrderSampler from '../test/generated-artifacts/TestNativeOrderSampler.json'; import * as UniswapSampler from '../test/generated-artifacts/UniswapSampler.json'; import * as UniswapV2Sampler from '../test/generated-artifacts/UniswapV2Sampler.json'; export const artifacts = { @@ -39,7 +41,6 @@ export const artifacts = { ERC20BridgeSampler: ERC20BridgeSampler as ContractArtifact, Eth2DaiSampler: Eth2DaiSampler as ContractArtifact, ICurve: ICurve as ContractArtifact, - IDevUtils: IDevUtils as ContractArtifact, IEth2Dai: IEth2Dai as ContractArtifact, IKyberHintHandler: IKyberHintHandler as ContractArtifact, IKyberNetwork: IKyberNetwork as ContractArtifact, @@ -47,15 +48,18 @@ export const artifacts = { IKyberStorage: IKyberStorage as ContractArtifact, ILiquidityProvider: ILiquidityProvider as ContractArtifact, ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact, + IMStable: IMStable as ContractArtifact, IMultiBridge: IMultiBridge as ContractArtifact, IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact, IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact, KyberSampler: KyberSampler as ContractArtifact, LiquidityProviderSampler: LiquidityProviderSampler as ContractArtifact, + MStableSampler: MStableSampler as ContractArtifact, MultiBridgeSampler: MultiBridgeSampler as ContractArtifact, NativeOrderSampler: NativeOrderSampler as ContractArtifact, SamplerUtils: SamplerUtils as ContractArtifact, UniswapSampler: UniswapSampler as ContractArtifact, UniswapV2Sampler: UniswapV2Sampler as ContractArtifact, TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact, + TestNativeOrderSampler: TestNativeOrderSampler as ContractArtifact, }; diff --git a/contracts/integrations/test/bridge_sampler/bridge_sampler_mainnet_test.ts b/packages/asset-swapper/test/contracts/bridge_sampler_mainnet_test.ts similarity index 97% rename from contracts/integrations/test/bridge_sampler/bridge_sampler_mainnet_test.ts rename to packages/asset-swapper/test/contracts/bridge_sampler_mainnet_test.ts index 5fe0d3f7d4..0b394793dd 100644 --- a/contracts/integrations/test/bridge_sampler/bridge_sampler_mainnet_test.ts +++ b/packages/asset-swapper/test/contracts/bridge_sampler_mainnet_test.ts @@ -1,10 +1,14 @@ -import { artifacts, ERC20BridgeSamplerContract } from '@0x/contracts-erc20-bridge-sampler'; import { blockchainTests, describe, expect, toBaseUnitAmount, Web3ProviderEngine } from '@0x/contracts-test-utils'; import { RPCSubprovider } from '@0x/subproviders'; import { BigNumber, providerUtils } from '@0x/utils'; +import { artifacts } from '../artifacts'; +import { ERC20BridgeSamplerContract } from '../wrappers'; + export const VB = '0x6cc5f688a315f3dc28a7781717a9a798a59fda7b'; +// tslint:disable: custom-no-magic-numbers + blockchainTests.skip('Mainnet Sampler Tests', env => { let testContract: ERC20BridgeSamplerContract; const fakeSamplerAddress = '0x1111111111111111111111111111111111111111'; diff --git a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts b/packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts similarity index 92% rename from contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts rename to packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts index e4783468ac..6a871797d8 100644 --- a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts +++ b/packages/asset-swapper/test/contracts/erc20_bridge_sampler_test.ts @@ -10,12 +10,16 @@ import { Order } from '@0x/types'; import { BigNumber, hexUtils } from '@0x/utils'; import * as _ from 'lodash'; -import { artifacts } from './artifacts'; +import { artifacts } from '../artifacts'; import { DummyLiquidityProviderContract, DummyLiquidityProviderRegistryContract, TestERC20BridgeSamplerContract, -} from './wrappers'; +} from '../wrappers'; + +// tslint:disable: custom-no-magic-numbers + +const { NULL_ADDRESS } = constants; blockchainTests('erc20-bridge-sampler', env => { let testContract: TestERC20BridgeSamplerContract; @@ -33,7 +37,6 @@ blockchainTests('erc20-bridge-sampler', env => { const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR'; const MAKER_TOKEN = randomAddress(); const TAKER_TOKEN = randomAddress(); - let devUtilsAddress: string; before(async () => { testContract = await TestERC20BridgeSamplerContract.deployFrom0xArtifactAsync( @@ -42,8 +45,6 @@ blockchainTests('erc20-bridge-sampler', env => { env.txDefaults, {}, ); - // TestERC20BridgeSampler stubs DevUtils - devUtilsAddress = testContract.address; }); function getPackedHash(...args: string[]): string { @@ -209,12 +210,7 @@ blockchainTests('erc20-bridge-sampler', env => { function getDeterministicFillableTakerAssetAmount(order: Order): BigNumber { const hash = getPackedHash(hexUtils.leftPad(order.salt)); - const orderStatus = new BigNumber(hash).mod(100).toNumber() > 90 ? 5 : 3; - const isValidSignature = !!new BigNumber(hash).mod(2).toNumber(); - if (orderStatus !== 3 || !isValidSignature) { - return constants.ZERO_AMOUNT; - } - return order.takerAssetAmount.minus(new BigNumber(hash).mod(order.takerAssetAmount)); + return new BigNumber(hash).mod(order.takerAssetAmount); } function getDeterministicFillableMakerAssetAmount(order: Order): BigNumber { @@ -272,44 +268,15 @@ blockchainTests('erc20-bridge-sampler', env => { const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const expected = orders.map(getDeterministicFillableTakerAssetAmount); const actual = await testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) + .getOrderFillableTakerAssetAmounts(orders, signatures, NULL_ADDRESS) .callAsync(); expect(actual).to.deep.eq(expected); }); it('returns empty for no orders', async () => { - const actual = await testContract.getOrderFillableTakerAssetAmounts([], [], devUtilsAddress).callAsync(); + const actual = await testContract.getOrderFillableTakerAssetAmounts([], [], NULL_ADDRESS).callAsync(); expect(actual).to.deep.eq([]); }); - - it('returns zero for an order with zero maker asset amount', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - orders[0].makerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, i => hexUtils.random()); - const actual = await testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); - - it('returns zero for an order with zero taker asset amount', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - orders[0].takerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, i => hexUtils.random()); - const actual = await testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); - - it('returns zero for an order with an empty signature', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES); - const actual = await testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); }); describe('getOrderFillableMakerAssetAmounts()', () => { @@ -318,44 +285,15 @@ blockchainTests('erc20-bridge-sampler', env => { const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const expected = orders.map(getDeterministicFillableMakerAssetAmount); const actual = await testContract - .getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress) + .getOrderFillableMakerAssetAmounts(orders, signatures, NULL_ADDRESS) .callAsync(); expect(actual).to.deep.eq(expected); }); it('returns empty for no orders', async () => { - const actual = await testContract.getOrderFillableMakerAssetAmounts([], [], devUtilsAddress).callAsync(); + const actual = await testContract.getOrderFillableMakerAssetAmounts([], [], NULL_ADDRESS).callAsync(); expect(actual).to.deep.eq([]); }); - - it('returns zero for an order with zero maker asset amount', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - orders[0].makerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, i => hexUtils.random()); - const actual = await testContract - .getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); - - it('returns zero for an order with zero taker asset amount', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - orders[0].takerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, i => hexUtils.random()); - const actual = await testContract - .getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); - - it('returns zero for an order with an empty signature', async () => { - const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); - const signatures: string[] = _.times(orders.length, () => constants.NULL_BYTES); - const actual = await testContract - .getOrderFillableMakerAssetAmounts(orders, signatures, devUtilsAddress) - .callAsync(); - expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); - }); }); blockchainTests.resets('sampleSellsFromKyberNetwork()', () => { @@ -1036,7 +974,7 @@ blockchainTests('erc20-bridge-sampler', env => { const expected = orders.map(getDeterministicFillableTakerAssetAmount); const calls = [ testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) + .getOrderFillableTakerAssetAmounts(orders, signatures, NULL_ADDRESS) .getABIEncodedTransactionData(), ]; const r = await testContract.batchCall(calls).callAsync(); @@ -1055,10 +993,10 @@ blockchainTests('erc20-bridge-sampler', env => { ]; const calls = [ testContract - .getOrderFillableTakerAssetAmounts(orders[0], signatures, devUtilsAddress) + .getOrderFillableTakerAssetAmounts(orders[0], signatures, NULL_ADDRESS) .getABIEncodedTransactionData(), testContract - .getOrderFillableMakerAssetAmounts(orders[1], signatures, devUtilsAddress) + .getOrderFillableMakerAssetAmounts(orders[1], signatures, NULL_ADDRESS) .getABIEncodedTransactionData(), ]; const r = await testContract.batchCall(calls).callAsync(); @@ -1081,7 +1019,7 @@ blockchainTests('erc20-bridge-sampler', env => { testContract .batchCall([ testContract - .getOrderFillableTakerAssetAmounts(orders, signatures, devUtilsAddress) + .getOrderFillableTakerAssetAmounts(orders, signatures, NULL_ADDRESS) .getABIEncodedTransactionData(), ]) .getABIEncodedTransactionData(), diff --git a/packages/asset-swapper/test/contracts/native_order_sampler_test.ts b/packages/asset-swapper/test/contracts/native_order_sampler_test.ts new file mode 100644 index 0000000000..021ce4e32e --- /dev/null +++ b/packages/asset-swapper/test/contracts/native_order_sampler_test.ts @@ -0,0 +1,313 @@ +import { + assertIntegerRoughlyEquals, + blockchainTests, + constants, + expect, + getRandomInteger, + randomAddress, +} from '@0x/contracts-test-utils'; +import { Order } from '@0x/types'; +import { BigNumber, hexUtils } from '@0x/utils'; +import * as _ from 'lodash'; + +import { artifacts } from '../artifacts'; +import { TestNativeOrderSamplerContract } from '../wrappers'; + +const { NULL_BYTES, ZERO_AMOUNT } = constants; + +// tslint:disable: custom-no-magic-numbers + +blockchainTests.resets('NativeOrderSampler contract', env => { + let testContract: TestNativeOrderSamplerContract; + let makerToken: string; + let takerToken: string; + let feeToken: string; + let erc20Proxy: string; + const ERC20_PROXY_ID = '0xf47261b0'; + const VALID_SIGNATURE = '0x01'; + const INVALID_SIGNATURE = '0x00'; + + before(async () => { + testContract = await TestNativeOrderSamplerContract.deployFrom0xArtifactAsync( + artifacts.TestNativeOrderSampler, + env.provider, + env.txDefaults, + {}, + ); + erc20Proxy = await testContract.getAssetProxy(ERC20_PROXY_ID).callAsync(); + const NUM_TOKENS = new BigNumber(3); + [makerToken, takerToken, feeToken] = await testContract.createTokens(NUM_TOKENS).callAsync(); + await testContract.createTokens(NUM_TOKENS).awaitTransactionSuccessAsync(); + }); + + function getPackedHash(...args: string[]): string { + return hexUtils.hash(hexUtils.concat(...args.map(a => hexUtils.toHex(a)))); + } + + interface OrderInfo { + orderHash: string; + orderStatus: number; + orderTakerAssetFilledAmount: BigNumber; + } + + function getOrderInfo(order: Order): OrderInfo { + const hash = getPackedHash(hexUtils.leftPad(order.salt)); + const orderStatus = order.salt.mod(255).eq(0) ? 3 : 5; + const filledAmount = order.expirationTimeSeconds; + return { + orderStatus, + orderHash: hash, + orderTakerAssetFilledAmount: filledAmount, + }; + } + + function createFillableOrderSalt(): BigNumber { + return new BigNumber(hexUtils.concat(hexUtils.slice(hexUtils.random(), 0, -1), '0x01')); + } + + function createUnfillableOrderSalt(): BigNumber { + return new BigNumber(hexUtils.concat(hexUtils.slice(hexUtils.random(), 0, -1), '0xff')); + } + + function getOrderFillableTakerAmount(order: Order): BigNumber { + return order.takerAssetAmount.minus(getOrderInfo(order).orderTakerAssetFilledAmount); + } + + function getERC20AssetData(tokenAddress: string): string { + return hexUtils.concat(ERC20_PROXY_ID, hexUtils.leftPad(tokenAddress)); + } + + function createOrder(fields: Partial = {}, filledTakerAssetAmount: BigNumber = ZERO_AMOUNT): Order { + return { + chainId: 1337, + exchangeAddress: randomAddress(), + makerAddress: randomAddress(), + takerAddress: randomAddress(), + senderAddress: randomAddress(), + feeRecipientAddress: randomAddress(), + makerAssetAmount: getRandomInteger(1e18, 10e18), + takerAssetAmount: getRandomInteger(1e18, 10e18), + makerFee: getRandomInteger(1e18, 10e18), + takerFee: getRandomInteger(1e18, 10e18), + makerAssetData: getERC20AssetData(makerToken), + takerAssetData: getERC20AssetData(takerToken), + makerFeeAssetData: getERC20AssetData(feeToken), + takerFeeAssetData: getERC20AssetData(randomAddress()), + salt: createFillableOrderSalt(), + // Expiration time will be used to determine filled amount. + expirationTimeSeconds: filledTakerAssetAmount, + ...fields, + }; + } + + async function fundMakerAsync( + order: Order, + assetData: string, + balanceScaling: number = 1, + allowanceScaling: number = 1, + ): Promise { + let token; + let amount; + if (assetData === order.makerAssetData) { + token = makerToken; + amount = + order.makerAssetData === order.makerFeeAssetData + ? order.makerAssetAmount.plus(order.makerFee) + : order.makerAssetAmount; + } else { + token = feeToken; + amount = order.makerFee; + } + amount = amount.times(getOrderFillableTakerAmount(order).div(BigNumber.max(1, order.takerAssetAmount))); + await testContract + .setTokenBalanceAndAllowance( + token, + order.makerAddress, + erc20Proxy, + amount.times(balanceScaling).integerValue(), + amount.times(allowanceScaling).integerValue(), + ) + .awaitTransactionSuccessAsync(); + } + + describe('getOrderFillableTakerAmount()', () => { + it('returns the full amount for a fully funded order', async () => { + const order = createOrder(); + const expected = getOrderFillableTakerAmount(order); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(actual).to.bignumber.eq(expected); + }); + + it('returns the full amount for a fully funded order without maker fees', async () => { + const order = createOrder({ makerFee: ZERO_AMOUNT }); + const expected = getOrderFillableTakerAmount(order); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(actual).to.bignumber.eq(expected); + }); + + it('returns the full amount for a fully funded order without maker fee asset data', async () => { + const order = createOrder({ makerFeeAssetData: NULL_BYTES }); + const expected = getOrderFillableTakerAmount(order); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(actual).to.bignumber.eq(expected); + }); + + it('returns the full amount for a fully funded order with maker fees denominated in the maker asset', async () => { + const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) }); + const expected = getOrderFillableTakerAmount(order); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(actual).to.bignumber.eq(expected); + }); + + it('returns partial amount with insufficient maker asset balance', async () => { + const order = createOrder(); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData, 0.5); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns partial amount with insufficient maker asset allowance', async () => { + const order = createOrder(); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData, 1, 0.5); + await fundMakerAsync(order, order.makerFeeAssetData); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns partial amount with insufficient maker fee asset balance', async () => { + const order = createOrder(); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData, 0.5); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns partial amount with insufficient maker fee asset allowance', async () => { + const order = createOrder(); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData, 1, 0.5); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns partial amount with insufficient maker asset balance (maker asset fees)', async () => { + const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) }); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData, 0.5); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns partial amount with insufficient maker asset allowance (maker asset fees)', async () => { + const order = createOrder({ makerFeeAssetData: getERC20AssetData(makerToken) }); + const expected = getOrderFillableTakerAmount(order) + .times(0.5) + .integerValue(BigNumber.ROUND_DOWN); + await fundMakerAsync(order, order.makerAssetData, 1, 0.5); + const actual = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + assertIntegerRoughlyEquals(actual, expected, 100); + }); + + it('returns zero for an that is not fillable', async () => { + const order = { + ...createOrder(), + salt: createUnfillableOrderSalt(), + }; + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const fillableTakerAmount = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT); + }); + + it('returns zero for an order with zero maker asset amount', async () => { + const order = { + ...createOrder(), + makerAssetAmount: ZERO_AMOUNT, + }; + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const fillableTakerAmount = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT); + }); + + it('returns zero for an order with zero taker asset amount', async () => { + const order = { + ...createOrder(), + takerAssetAmount: ZERO_AMOUNT, + }; + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const fillableTakerAmount = await testContract + .getOrderFillableTakerAmount(order, VALID_SIGNATURE, testContract.address) + .callAsync(); + expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT); + }); + + it('returns zero for an order with an empty signature', async () => { + const order = createOrder(); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const fillableTakerAmount = await testContract + .getOrderFillableTakerAmount(order, NULL_BYTES, testContract.address) + .callAsync(); + expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT); + }); + + it('returns zero for an order with an invalid signature', async () => { + const order = createOrder(); + await fundMakerAsync(order, order.makerAssetData); + await fundMakerAsync(order, order.makerFeeAssetData); + const fillableTakerAmount = await testContract + .getOrderFillableTakerAmount(order, INVALID_SIGNATURE, testContract.address) + .callAsync(); + expect(fillableTakerAmount).to.bignumber.eq(ZERO_AMOUNT); + }); + }); +}); diff --git a/packages/asset-swapper/test/dex_sampler_test.ts b/packages/asset-swapper/test/dex_sampler_test.ts index a254678686..ad655d3857 100644 --- a/packages/asset-swapper/test/dex_sampler_test.ts +++ b/packages/asset-swapper/test/dex_sampler_test.ts @@ -32,7 +32,7 @@ describe('DexSampler tests', () => { const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN); const wethAddress = getContractAddressesForChainOrThrow(CHAIN_ID).etherToken; - const devUtilsAddress = getContractAddressesForChainOrThrow(CHAIN_ID).devUtils; + const exchangeAddress = getContractAddressesForChainOrThrow(CHAIN_ID).exchange; describe('getSampleAmounts()', () => { const FILL_AMOUNT = getRandomInteger(1, 1e18); @@ -106,7 +106,7 @@ describe('DexSampler tests', () => { }); const dexOrderSampler = new DexOrderSampler(sampler); const [fillableAmounts] = await dexOrderSampler.executeAsync( - DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress), + DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, exchangeAddress), ); expect(fillableAmounts).to.deep.eq(expectedFillableAmounts); }); @@ -122,7 +122,7 @@ describe('DexSampler tests', () => { }); const dexOrderSampler = new DexOrderSampler(sampler); const [fillableAmounts] = await dexOrderSampler.executeAsync( - DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress), + DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, exchangeAddress), ); expect(fillableAmounts).to.deep.eq(expectedFillableAmounts); }); @@ -632,8 +632,8 @@ describe('DexSampler tests', () => { }); const dexOrderSampler = new DexOrderSampler(sampler); const [fillableMakerAmounts, fillableTakerAmounts] = await dexOrderSampler.executeAsync( - DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, devUtilsAddress), - DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, devUtilsAddress), + DexOrderSampler.ops.getOrderFillableMakerAmounts(ORDERS, exchangeAddress), + DexOrderSampler.ops.getOrderFillableTakerAmounts(ORDERS, exchangeAddress), ); expect(fillableMakerAmounts).to.deep.eq(expectedFillableMakerAmounts); expect(fillableTakerAmounts).to.deep.eq(expectedFillableTakerAmounts); diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index bbf8d39729..efba5220e7 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -31,11 +31,6 @@ const TAKER_ASSET_DATA = assetDataUtils.encodeERC20AssetData(TAKER_TOKEN); describe('MarketOperationUtils tests', () => { const CHAIN_ID = 1; const contractAddresses = { ...getContractAddressesForChainOrThrow(CHAIN_ID), multiBridge: NULL_ADDRESS }; - const ETH2DAI_BRIDGE_ADDRESS = contractAddresses.eth2DaiBridge; - const KYBER_BRIDGE_ADDRESS = contractAddresses.kyberBridge; - const UNISWAP_BRIDGE_ADDRESS = contractAddresses.uniswapBridge; - const UNISWAP_V2_BRIDGE_ADDRESS = contractAddresses.uniswapV2Bridge; - const CURVE_BRIDGE_ADDRESS = contractAddresses.curveBridge; let originalSamplerOperations: any; before(() => { @@ -79,16 +74,18 @@ describe('MarketOperationUtils tests', () => { } const { bridgeAddress } = bridgeData; switch (bridgeAddress) { - case KYBER_BRIDGE_ADDRESS.toLowerCase(): + case contractAddresses.kyberBridge.toLowerCase(): return ERC20BridgeSource.Kyber; - case ETH2DAI_BRIDGE_ADDRESS.toLowerCase(): + case contractAddresses.eth2DaiBridge.toLowerCase(): return ERC20BridgeSource.Eth2Dai; - case UNISWAP_BRIDGE_ADDRESS.toLowerCase(): + case contractAddresses.uniswapBridge.toLowerCase(): return ERC20BridgeSource.Uniswap; - case UNISWAP_V2_BRIDGE_ADDRESS.toLowerCase(): + case contractAddresses.uniswapV2Bridge.toLowerCase(): return ERC20BridgeSource.UniswapV2; - case CURVE_BRIDGE_ADDRESS.toLowerCase(): + case contractAddresses.curveBridge.toLowerCase(): return ERC20BridgeSource.Curve; + case contractAddresses.mStableBridge.toLowerCase(): + return ERC20BridgeSource.MStable; default: break; } @@ -294,6 +291,7 @@ describe('MarketOperationUtils tests', () => { [ERC20BridgeSource.Curve]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.LiquidityProvider]: _.times(NUM_SAMPLES, () => 0), [ERC20BridgeSource.MultiBridge]: _.times(NUM_SAMPLES, () => 0), + [ERC20BridgeSource.MStable]: _.times(NUM_SAMPLES, () => 0), }; interface FillDataBySource { @@ -425,7 +423,12 @@ describe('MarketOperationUtils tests', () => { sampleDistributionBase: 1, bridgeSlippage: 0, maxFallbackSlippage: 100, - excludedSources: [ERC20BridgeSource.UniswapV2, ERC20BridgeSource.Curve, ERC20BridgeSource.Balancer], + excludedSources: [ + ERC20BridgeSource.UniswapV2, + ERC20BridgeSource.Curve, + ERC20BridgeSource.Balancer, + ERC20BridgeSource.MStable, + ], allowFallback: false, shouldBatchBridgeOrders: false, }; @@ -462,7 +465,7 @@ describe('MarketOperationUtils tests', () => { ...DEFAULT_OPTS, excludedSources: [], }); - expect(sourcesPolled.sort()).to.deep.eq(SELL_SOURCES.slice().sort()); + expect(sourcesPolled.sort()).to.deep.equals(SELL_SOURCES.slice().sort()); }); it('polls the liquidity provider when the registry is provided in the arguments', async () => { @@ -484,7 +487,7 @@ describe('MarketOperationUtils tests', () => { ...DEFAULT_OPTS, excludedSources: [], }); - expect(args.sources.sort()).to.deep.eq( + expect(args.sources.sort()).to.deep.equals( SELL_SOURCES.concat([ERC20BridgeSource.LiquidityProvider]).sort(), ); expect(args.liquidityProviderAddress).to.eql(registryAddress); @@ -503,7 +506,7 @@ describe('MarketOperationUtils tests', () => { ...DEFAULT_OPTS, excludedSources, }); - expect(sourcesPolled.sort()).to.deep.eq(_.without(SELL_SOURCES, ...excludedSources).sort()); + expect(sourcesPolled.sort()).to.deep.equals(_.without(SELL_SOURCES, ...excludedSources).sort()); }); it('generates bridge orders with correct asset data', async () => { @@ -836,6 +839,7 @@ describe('MarketOperationUtils tests', () => { ERC20BridgeSource.UniswapV2, ERC20BridgeSource.Curve, ERC20BridgeSource.Balancer, + ERC20BridgeSource.MStable, ], allowFallback: false, shouldBatchBridgeOrders: false, @@ -873,7 +877,7 @@ describe('MarketOperationUtils tests', () => { ...DEFAULT_OPTS, excludedSources: [], }); - expect(sourcesPolled).to.deep.eq(BUY_SOURCES); + expect(sourcesPolled.sort()).to.deep.equals(BUY_SOURCES.sort()); }); it('polls the liquidity provider when the registry is provided in the arguments', async () => { @@ -914,7 +918,7 @@ describe('MarketOperationUtils tests', () => { ...DEFAULT_OPTS, excludedSources, }); - expect(sourcesPolled).to.deep.eq(_.without(BUY_SOURCES, ...excludedSources)); + expect(sourcesPolled.sort()).to.deep.eq(_.without(BUY_SOURCES, ...excludedSources).sort()); }); it('generates bridge orders with correct asset data', async () => { diff --git a/packages/asset-swapper/test/utils/mock_sampler_contract.ts b/packages/asset-swapper/test/utils/mock_sampler_contract.ts index be9fd575a2..15f928406b 100644 --- a/packages/asset-swapper/test/utils/mock_sampler_contract.ts +++ b/packages/asset-swapper/test/utils/mock_sampler_contract.ts @@ -1,9 +1,10 @@ import { ContractFunctionObj } from '@0x/base-contract'; -import { ERC20BridgeSamplerContract } from '@0x/contract-wrappers'; import { constants } from '@0x/contracts-test-utils'; import { Order } from '@0x/types'; import { BigNumber, hexUtils } from '@0x/utils'; +import { ERC20BridgeSamplerContract } from '../../src/wrappers'; + export type GetOrderFillableAssetAmountResult = BigNumber[]; export type GetOrderFillableAssetAmountHandler = ( orders: Order[], @@ -59,6 +60,8 @@ interface Handlers { sampleBuysFromLiquidityProviderRegistry: SampleSellsLPHandler; } +// tslint:disable: no-unbound-method + export class MockSamplerContract extends ERC20BridgeSamplerContract { private readonly _handlers: Partial = {}; diff --git a/contracts/erc20-bridge-sampler/test/wrappers.ts b/packages/asset-swapper/test/wrappers.ts similarity index 90% rename from contracts/erc20-bridge-sampler/test/wrappers.ts rename to packages/asset-swapper/test/wrappers.ts index 33964f8fcb..cb27839ae7 100644 --- a/contracts/erc20-bridge-sampler/test/wrappers.ts +++ b/packages/asset-swapper/test/wrappers.ts @@ -10,7 +10,6 @@ export * from '../test/generated-wrappers/dummy_liquidity_provider_registry'; export * from '../test/generated-wrappers/erc20_bridge_sampler'; export * from '../test/generated-wrappers/eth2_dai_sampler'; export * from '../test/generated-wrappers/i_curve'; -export * from '../test/generated-wrappers/i_dev_utils'; export * from '../test/generated-wrappers/i_eth2_dai'; export * from '../test/generated-wrappers/i_kyber_hint_handler'; export * from '../test/generated-wrappers/i_kyber_network'; @@ -18,14 +17,17 @@ export * from '../test/generated-wrappers/i_kyber_network_proxy'; export * from '../test/generated-wrappers/i_kyber_storage'; export * from '../test/generated-wrappers/i_liquidity_provider'; export * from '../test/generated-wrappers/i_liquidity_provider_registry'; +export * from '../test/generated-wrappers/i_m_stable'; export * from '../test/generated-wrappers/i_multi_bridge'; export * from '../test/generated-wrappers/i_uniswap_exchange_quotes'; export * from '../test/generated-wrappers/i_uniswap_v2_router01'; export * from '../test/generated-wrappers/kyber_sampler'; export * from '../test/generated-wrappers/liquidity_provider_sampler'; +export * from '../test/generated-wrappers/m_stable_sampler'; export * from '../test/generated-wrappers/multi_bridge_sampler'; export * from '../test/generated-wrappers/native_order_sampler'; export * from '../test/generated-wrappers/sampler_utils'; export * from '../test/generated-wrappers/test_erc20_bridge_sampler'; +export * from '../test/generated-wrappers/test_native_order_sampler'; export * from '../test/generated-wrappers/uniswap_sampler'; export * from '../test/generated-wrappers/uniswap_v2_sampler'; diff --git a/packages/asset-swapper/tsconfig.json b/packages/asset-swapper/tsconfig.json index 2ee711adcc..cb1f20d502 100644 --- a/packages/asset-swapper/tsconfig.json +++ b/packages/asset-swapper/tsconfig.json @@ -1,8 +1,40 @@ { "extends": "../../tsconfig", - "compilerOptions": { - "outDir": "lib", - "rootDir": "." - }, - "include": ["./src/**/*", "./test/**/*"] + "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true }, + "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"], + "files": [ + "generated-artifacts/DummyLiquidityProvider.json", + "generated-artifacts/DummyLiquidityProviderRegistry.json", + "generated-artifacts/ERC20BridgeSampler.json", + "generated-artifacts/ILiquidityProvider.json", + "generated-artifacts/ILiquidityProviderRegistry.json", + "test/generated-artifacts/ApproximateBuys.json", + "test/generated-artifacts/CurveSampler.json", + "test/generated-artifacts/DummyLiquidityProvider.json", + "test/generated-artifacts/DummyLiquidityProviderRegistry.json", + "test/generated-artifacts/ERC20BridgeSampler.json", + "test/generated-artifacts/Eth2DaiSampler.json", + "test/generated-artifacts/ICurve.json", + "test/generated-artifacts/IEth2Dai.json", + "test/generated-artifacts/IKyberHintHandler.json", + "test/generated-artifacts/IKyberNetwork.json", + "test/generated-artifacts/IKyberNetworkProxy.json", + "test/generated-artifacts/IKyberStorage.json", + "test/generated-artifacts/ILiquidityProvider.json", + "test/generated-artifacts/ILiquidityProviderRegistry.json", + "test/generated-artifacts/IMStable.json", + "test/generated-artifacts/IMultiBridge.json", + "test/generated-artifacts/IUniswapExchangeQuotes.json", + "test/generated-artifacts/IUniswapV2Router01.json", + "test/generated-artifacts/KyberSampler.json", + "test/generated-artifacts/LiquidityProviderSampler.json", + "test/generated-artifacts/MStableSampler.json", + "test/generated-artifacts/MultiBridgeSampler.json", + "test/generated-artifacts/NativeOrderSampler.json", + "test/generated-artifacts/SamplerUtils.json", + "test/generated-artifacts/TestERC20BridgeSampler.json", + "test/generated-artifacts/TestNativeOrderSampler.json", + "test/generated-artifacts/UniswapSampler.json", + "test/generated-artifacts/UniswapV2Sampler.json" + ] } diff --git a/packages/asset-swapper/tslint.json b/packages/asset-swapper/tslint.json index dd9053357e..3342b321c7 100644 --- a/packages/asset-swapper/tslint.json +++ b/packages/asset-swapper/tslint.json @@ -1,3 +1,9 @@ { - "extends": ["@0x/tslint-config"] + "extends": ["@0x/tslint-config"], + "rules": { + "max-file-line-count": false + }, + "linterOptions": { + "exclude": ["src/artifacts.ts", "test/artifacts.ts"] + } } diff --git a/packages/contract-addresses/CHANGELOG.json b/packages/contract-addresses/CHANGELOG.json index 0031849696..1e751cf678 100644 --- a/packages/contract-addresses/CHANGELOG.json +++ b/packages/contract-addresses/CHANGELOG.json @@ -17,6 +17,14 @@ { "note": "Redeploy previously unverified contracts on testnets", "pr": 2656 + }, + { + "note": "Deploy FQT", + "pr": 2667 + }, + { + "note": "Deploy `MStableBridge` on Mainnet", + "pr": 2662 } ] }, diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index 18793fd4bb..c4ecda434f 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -39,10 +39,11 @@ "exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb", "exchangeProxyTransformerDeployer": "0x80a36559ab9a497fb658325ed771a584eb0f13da", "exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18", + "mStableBridge": "0x2bf04fcea05f0989a14d9afa37aa376baca6b2b3", "transformers": { "wethTransformer": "0x7bab5f7299e1ca123bb44eb71e6c89be7e558cc8", "payTakerTransformer": "0xe8c07a119452b55eee2f999478aab97f3656d841", - "fillQuoteTransformer": "0xbc33dd7a09da8ca943517a0fb786bcf0192f8be2", + "fillQuoteTransformer": "0xa8c8cf29699f223766f47fe79e2b7eb1a90e08c8", "affiliateFeeTransformer": "0x9d7174f55b50dad2e417bd567ad2da1ae4eef76d" } }, @@ -86,10 +87,11 @@ "exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb", "exchangeProxyTransformerDeployer": "0x80a36559ab9a497fb658325ed771a584eb0f13da", "exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18", + "mStableBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x7bab5f7299e1ca123bb44eb71e6c89be7e558cc8", "payTakerTransformer": "0xe8c07a119452b55eee2f999478aab97f3656d841", - "fillQuoteTransformer": "0xfadbeff43a07dedeb69eda5590be1b78be3d1044", + "fillQuoteTransformer": "0x58faf8e7bad3131d00d4deacb7488744818b9570", "affiliateFeeTransformer": "0x9d7174f55b50dad2e417bd567ad2da1ae4eef76d" } }, @@ -133,10 +135,11 @@ "exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb", "exchangeProxyTransformerDeployer": "0x80a36559ab9a497fb658325ed771a584eb0f13da", "exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18", + "mStableBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x7bab5f7299e1ca123bb44eb71e6c89be7e558cc8", "payTakerTransformer": "0xe8c07a119452b55eee2f999478aab97f3656d841", - "fillQuoteTransformer": "0x454cC891dc428Be81d1d6Fd3dd7026a752FBFBc9", + "fillQuoteTransformer": "0x2ebe42dab6c6dec58ba494d111d1464836216c2a", "affiliateFeeTransformer": "0x9d7174f55b50dad2e417bd567ad2da1ae4eef76d" } }, @@ -180,10 +183,11 @@ "exchangeProxyAllowanceTarget": "0xf740b67da229f2f10bcbd38a7979992fcc71b8eb", "exchangeProxyTransformerDeployer": "0x80a36559ab9a497fb658325ed771a584eb0f13da", "exchangeProxyFlashWallet": "0x22f9dcf4647084d6c31b2765f6910cd85c178c18", + "mStableBridge": "0x0000000000000000000000000000000000000000", "transformers": { "wethTransformer": "0x7bab5f7299e1ca123bb44eb71e6c89be7e558cc8", "payTakerTransformer": "0xe8c07a119452b55eee2f999478aab97f3656d841", - "fillQuoteTransformer": "0xA8c8Cf29699F223766F47FE79e2B7eB1a90e08C8", + "fillQuoteTransformer": "0x10c394406d2b15fb8e67b9a7a0dd03fa4d3e8099", "affiliateFeeTransformer": "0x9d7174f55b50dad2e417bd567ad2da1ae4eef76d" } }, @@ -210,7 +214,7 @@ "uniswapBridge": "0x0000000000000000000000000000000000000000", "uniswapV2Bridge": "0x0000000000000000000000000000000000000000", "eth2DaiBridge": "0x0000000000000000000000000000000000000000", - "erc20BridgeSampler": "0x2c530e4ecc573f11bd72cf5fdf580d134d25f15f", + "erc20BridgeSampler": "0x0000000000000000000000000000000000000000", "kyberBridge": "0x0000000000000000000000000000000000000000", "chaiBridge": "0x0000000000000000000000000000000000000000", "dydxBridge": "0x0000000000000000000000000000000000000000", @@ -223,15 +227,16 @@ "multiBridge": "0x0000000000000000000000000000000000000000", "balancerBridge": "0x0000000000000000000000000000000000000000", "exchangeProxyGovernor": "0x0000000000000000000000000000000000000000", - "exchangeProxy": "0x2ebb94cc79d7d0f1195300aaf191d118f53292a8", - "exchangeProxyAllowanceTarget": "0x3eab3df72fd584b50184ff7d988a0d8f9328c866", + "exchangeProxy": "0x5315e44798395d4a952530d131249fe00f554565", + "exchangeProxyAllowanceTarget": "0x8362c3ebd90041b30ec45908332e592721642637", "exchangeProxyTransformerDeployer": "0x5409ed021d9299bf6814279a6a1411a7e866a631", - "exchangeProxyFlashWallet": "0x8362c3ebd90041b30ec45908332e592721642637", + "exchangeProxyFlashWallet": "0xb9682a8e7920b431f1d412b8510f0077410c8faa", + "mStableBridge": "0x0000000000000000000000000000000000000000", "transformers": { - "wethTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3", - "payTakerTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5", - "fillQuoteTransformer": "0xc7124963ab16c33e5bf421d4c0090116622b3074", - "affiliateFeeTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a" + "wethTransformer": "0x3f16ca81691dab9184cb4606c361d73c4fd2510a", + "payTakerTransformer": "0x7209185959d7227fb77274e1e88151d7c4c368d3", + "fillQuoteTransformer": "0xc6b0d3c45a6b5092808196cb00df5c357d55e1d5", + "affiliateFeeTransformer": "0x99356167edba8fbdc36959e3f5d0c43d1ba9c6db" } } } diff --git a/packages/contract-addresses/src/index.ts b/packages/contract-addresses/src/index.ts index cba8c904db..d2593d04a0 100644 --- a/packages/contract-addresses/src/index.ts +++ b/packages/contract-addresses/src/index.ts @@ -40,6 +40,7 @@ export interface ContractAddresses { exchangeProxyAllowanceTarget: string; exchangeProxyTransformerDeployer: string; exchangeProxyFlashWallet: string; + mStableBridge: string; transformers: { wethTransformer: string; payTakerTransformer: string; diff --git a/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json b/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json deleted file mode 100644 index e8eac88ee2..0000000000 --- a/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json +++ /dev/null @@ -1,504 +0,0 @@ -{ - "schemaVersion": "2.0.0", - "contractName": "ERC20BridgeSampler", - "compilerOutput": { - "abi": [ - { - "constant": true, - "inputs": [{ "internalType": "bytes[]", "name": "callDatas", "type": "bytes[]" }], - "name": "batchCall", - "outputs": [{ "internalType": "bytes[]", "name": "callResults", "type": "bytes[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "registryAddress", "type": "address" }, - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" } - ], - "name": "getLiquidityProviderFromRegistry", - "outputs": [{ "internalType": "address", "name": "providerAddress", "type": "address" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "makerAddress", "type": "address" }, - { "internalType": "address", "name": "takerAddress", "type": "address" }, - { "internalType": "address", "name": "feeRecipientAddress", "type": "address" }, - { "internalType": "address", "name": "senderAddress", "type": "address" }, - { "internalType": "uint256", "name": "makerAssetAmount", "type": "uint256" }, - { "internalType": "uint256", "name": "takerAssetAmount", "type": "uint256" }, - { "internalType": "uint256", "name": "makerFee", "type": "uint256" }, - { "internalType": "uint256", "name": "takerFee", "type": "uint256" }, - { "internalType": "uint256", "name": "expirationTimeSeconds", "type": "uint256" }, - { "internalType": "uint256", "name": "salt", "type": "uint256" }, - { "internalType": "bytes", "name": "makerAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "takerAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "makerFeeAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "takerFeeAssetData", "type": "bytes" } - ], - "internalType": "struct LibOrder.Order[]", - "name": "orders", - "type": "tuple[]" - }, - { "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" }, - { "internalType": "address", "name": "devUtilsAddress", "type": "address" } - ], - "name": "getOrderFillableMakerAssetAmounts", - "outputs": [ - { "internalType": "uint256[]", "name": "orderFillableMakerAssetAmounts", "type": "uint256[]" } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "makerAddress", "type": "address" }, - { "internalType": "address", "name": "takerAddress", "type": "address" }, - { "internalType": "address", "name": "feeRecipientAddress", "type": "address" }, - { "internalType": "address", "name": "senderAddress", "type": "address" }, - { "internalType": "uint256", "name": "makerAssetAmount", "type": "uint256" }, - { "internalType": "uint256", "name": "takerAssetAmount", "type": "uint256" }, - { "internalType": "uint256", "name": "makerFee", "type": "uint256" }, - { "internalType": "uint256", "name": "takerFee", "type": "uint256" }, - { "internalType": "uint256", "name": "expirationTimeSeconds", "type": "uint256" }, - { "internalType": "uint256", "name": "salt", "type": "uint256" }, - { "internalType": "bytes", "name": "makerAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "takerAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "makerFeeAssetData", "type": "bytes" }, - { "internalType": "bytes", "name": "takerFeeAssetData", "type": "bytes" } - ], - "internalType": "struct LibOrder.Order[]", - "name": "orders", - "type": "tuple[]" - }, - { "internalType": "bytes[]", "name": "orderSignatures", "type": "bytes[]" }, - { "internalType": "address", "name": "devUtilsAddress", "type": "address" } - ], - "name": "getOrderFillableTakerAssetAmounts", - "outputs": [ - { "internalType": "uint256[]", "name": "orderFillableTakerAssetAmounts", "type": "uint256[]" } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "poolAddress", "type": "address" }, - { "internalType": "bytes4", "name": "sellQuoteFunctionSelector", "type": "bytes4" }, - { "internalType": "bytes4", "name": "buyQuoteFunctionSelector", "type": "bytes4" } - ], - "internalType": "struct CurveSampler.CurveInfo", - "name": "curveInfo", - "type": "tuple" - }, - { "internalType": "int128", "name": "fromTokenIdx", "type": "int128" }, - { "internalType": "int128", "name": "toTokenIdx", "type": "int128" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromCurve", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromEth2Dai", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromKyberNetwork", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "registryAddress", "type": "address" }, - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromLiquidityProviderRegistry", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromUniswap", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address[]", "name": "path", "type": "address[]" }, - { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleBuysFromUniswapV2", - "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "components": [ - { "internalType": "address", "name": "poolAddress", "type": "address" }, - { "internalType": "bytes4", "name": "sellQuoteFunctionSelector", "type": "bytes4" }, - { "internalType": "bytes4", "name": "buyQuoteFunctionSelector", "type": "bytes4" } - ], - "internalType": "struct CurveSampler.CurveInfo", - "name": "curveInfo", - "type": "tuple" - }, - { "internalType": "int128", "name": "fromTokenIdx", "type": "int128" }, - { "internalType": "int128", "name": "toTokenIdx", "type": "int128" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromCurve", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromEth2Dai", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "address", "name": "intermediateToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromEth2DaiHop", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromKyberNetwork", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "registryAddress", "type": "address" }, - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromLiquidityProviderRegistry", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "multibridge", "type": "address" }, - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "intermediateToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromMultiBridge", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address", "name": "takerToken", "type": "address" }, - { "internalType": "address", "name": "makerToken", "type": "address" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromUniswap", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { "internalType": "address[]", "name": "path", "type": "address[]" }, - { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } - ], - "name": "sampleSellsFromUniswapV2", - "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], - "payable": false, - "stateMutability": "view", - "type": "function" - } - ], - "devdoc": { - "methods": { - "batchCall(bytes[])": { - "details": "Call multiple public functions on this contract in a single transaction.", - "params": { "callDatas": "ABI-encoded call data for each function call." }, - "return": "callResults ABI-encoded results data for each call." - }, - "getLiquidityProviderFromRegistry(address,address,address)": { - "details": "Returns the address of a liquidity provider for the given market (takerToken, makerToken), from a registry of liquidity providers. Returns address(0) if no such provider exists in the registry.", - "params": { - "makerToken": "Maker asset managed by liquidity provider.", - "takerToken": "Taker asset managed by liquidity provider." - }, - "return": "providerAddress Address of the liquidity provider." - }, - "getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)": { - "details": "Queries the fillable taker asset amounts of native orders. Effectively ignores orders that have empty signatures or", - "params": { - "devUtilsAddress": "Address to the DevUtils contract.", - "orderSignatures": "Signatures for each respective order in `orders`.", - "orders": "Native orders to query." - }, - "return": "orderFillableMakerAssetAmounts How much maker asset can be filled by each order in `orders`." - }, - "getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)": { - "details": "Queries the fillable taker asset amounts of native orders. Effectively ignores orders that have empty signatures or maker/taker asset amounts (returning 0).", - "params": { - "devUtilsAddress": "Address to the DevUtils contract.", - "orderSignatures": "Signatures for each respective order in `orders`.", - "orders": "Native orders to query." - }, - "return": "orderFillableTakerAssetAmounts How much taker asset can be filled by each order in `orders`." - }, - "sampleBuysFromCurve((address,bytes4,bytes4),int128,int128,uint256[])": { - "details": "Sample buy quotes from Curve.", - "params": { - "curveInfo": "Curve information specific to this token pair.", - "fromTokenIdx": "Index of the taker token (what to sell).", - "makerTokenAmounts": "Maker token buy amount for each sample.", - "toTokenIdx": "Index of the maker token (what to buy)." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleBuysFromEth2Dai(address,address,uint256[])": { - "details": "Sample buy quotes from Eth2Dai/Oasis.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Maker token sell amount for each sample." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleBuysFromKyberNetwork(address,address,uint256[])": { - "details": "Sample buy quotes from Kyber.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "makerTokenAmounts": "Maker token buy amount for each sample.", - "takerToken": "Address of the taker token (what to sell)." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleBuysFromLiquidityProviderRegistry(address,address,address,uint256[])": { - "details": "Sample buy quotes from an arbitrary on-chain liquidity provider.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "makerTokenAmounts": "Maker token buy amount for each sample.", - "registryAddress": "Address of the liquidity provider registry contract.", - "takerToken": "Address of the taker token (what to sell)." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleBuysFromUniswap(address,address,uint256[])": { - "details": "Sample buy quotes from Uniswap.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "makerTokenAmounts": "Maker token sell amount for each sample.", - "takerToken": "Address of the taker token (what to sell)." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleBuysFromUniswapV2(address[],uint256[])": { - "details": "Sample buy quotes from UniswapV2.", - "params": { - "makerTokenAmounts": "Maker token buy amount for each sample.", - "path": "Token route. Should be takerToken -> makerToken." - }, - "return": "takerTokenAmounts Taker amounts sold at each maker token amount." - }, - "sampleSellsFromCurve((address,bytes4,bytes4),int128,int128,uint256[])": { - "details": "Sample sell quotes from Curve.", - "params": { - "curveInfo": "Curve information specific to this token pair.", - "fromTokenIdx": "Index of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample.", - "toTokenIdx": "Index of the maker token (what to buy)." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromEth2Dai(address,address,uint256[])": { - "details": "Sample sell quotes from Eth2Dai/Oasis.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromEth2DaiHop(address,address,address,uint256[])": { - "details": "Sample sell quotes from Eth2Dai/Oasis using a hop to an intermediate token. I.e WBTC/DAI via ETH or WBTC/ETH via DAI", - "params": { - "intermediateToken": "Address of the token to hop to.", - "makerToken": "Address of the maker token (what to buy).", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromKyberNetwork(address,address,uint256[])": { - "details": "Sample sell quotes from Kyber.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromLiquidityProviderRegistry(address,address,address,uint256[])": { - "details": "Sample sell quotes from an arbitrary on-chain liquidity provider.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "registryAddress": "Address of the liquidity provider registry contract.", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromMultiBridge(address,address,address,address,uint256[])": { - "details": "Sample sell quotes from MultiBridge.", - "params": { - "intermediateToken": "The address of the intermediate token to use in an indirect route.", - "makerToken": "Address of the maker token (what to buy).", - "multibridge": "Address of the MultiBridge contract.", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromUniswap(address,address,uint256[])": { - "details": "Sample sell quotes from Uniswap.", - "params": { - "makerToken": "Address of the maker token (what to buy).", - "takerToken": "Address of the taker token (what to sell).", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - }, - "sampleSellsFromUniswapV2(address[],uint256[])": { - "details": "Sample sell quotes from UniswapV2.", - "params": { - "path": "Token route. Should be takerToken -> makerToken", - "takerTokenAmounts": "Taker token sell amount for each sample." - }, - "return": "makerTokenAmounts Maker amounts bought at each taker token amount." - } - } - }, - "evm": { - "bytecode": { - "object": "0x608060405234801561001057600080fd5b50614784806100206000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806368be3cf2116100b2578063a2c28d4b11610081578063c7f7142e11610066578063c7f7142e1461027b578063e68248f71461029b578063e9a8e442146102ae57610136565b8063a2c28d4b14610255578063abffc7611461026857610136565b806368be3cf2146101fc5780636dd6b78d1461021c5780639209483b1461022f5780639f76ad351461024257610136565b80634703a7e61161010957806358306ba0116100ee57806358306ba0146101c357806360ee052a146101d657806364ee6ade146101e957610136565b80634703a7e61461019d5780634cb8e253146101b057610136565b80630cc6600b1461013b5780632d753aa41461016457806339b085ad1461017757806340bc03ae1461018a575b600080fd5b61014e610149366004613839565b6102c1565b60405161015b919061435f565b60405180910390f35b61014e610172366004613740565b61033b565b61014e610185366004613b5b565b610531565b61014e610198366004613eaa565b6107ee565b61014e6101ab366004613839565b6109a6565b61014e6101be366004613839565b610b82565b61014e6101d13660046137c6565b610cb5565b61014e6101e4366004613839565b610d4c565b61014e6101f7366004613839565b611001565b61020f61020a366004613aef565b6111c7565b60405161015b91906142e1565b61014e61022a366004613839565b61130d565b61014e61023d366004613eaa565b6115b5565b61014e6102503660046137c6565b6117e9565b61014e6102633660046137c6565b6119ed565b61014e610276366004613999565b611a53565b61028e6102893660046136f6565b611c3e565b60405161015b91906140d5565b61014e6102a9366004613999565b611d78565b61014e6102bc366004613b5b565b611f4b565b60606102cd8385611fee565b6103316040518060600160405280856040516020016102ec91906140d5565b60405160208183030381529060405281526020018660405160200161031191906140d5565b6040516020818303038152906040528152602001612061815250836121d9565b90505b9392505050565b60606000825190508060405190808252806020026020018201604052801561036d578160200160208202803883390190505b50915073ffffffffffffffffffffffffffffffffffffffff87166103915750610528565b60005b8181101561052557600060608973ffffffffffffffffffffffffffffffffffffffff1662061a80600073ffffffffffffffffffffffffffffffffffffffff16636e79e133905060e01b8b8b8b8b89815181106103ec57fe5b602002602001015160405160240161040794939291906141a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161049091906140b9565b6000604051808303818686fa925050503d80600081146104cc576040519150601f19603f3d011682016040523d82523d6000602084013e6104d1565b606091505b509092509050600082156104fa57818060200190516104f39190810190613d6e565b9050610502565b505050610525565b8086858151811061050f57fe5b6020908102919091010152505050600101610394565b50505b95945050505050565b6060835160405190808252806020026020018201604052801561055e578160200160208202803883390190505b50905060005b845181146107e65783818151811061057857fe5b602002602001015151600014806105a6575084818151811061059657fe5b6020026020010151608001516000145b806105c857508481815181106105b857fe5b602002602001015160a001516000145b156105ec5760008282815181106105db57fe5b6020026020010181815250506107de565b600060608473ffffffffffffffffffffffffffffffffffffffff166207a1208673ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b89868151811061063857fe5b602002602001015189878151811061064c57fe5b6020026020010151604051602401610665929190614466565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516106ee91906140b9565b6000604051808303818686fa925050503d806000811461072a576040519150601f19603f3d011682016040523d82523d6000602084013e61072f565b606091505b50915091508161075a57600084848151811061074757fe5b60200260200101818152505050506107de565b610762613533565b600080838060200190516107799190810190613f46565b9194509250905060038351600681111561078f57fe5b14158061079a575080155b156107be5760008787815181106107ad57fe5b6020026020010181815250506107d8565b818787815181106107cb57fe5b6020026020010181815250505b50505050505b600101610564565b509392505050565b606060008251905080604051908082528060200260200182016040528015610820578160200160208202803883390190505b50915060005b8181101561099c5760006060886000015173ffffffffffffffffffffffffffffffffffffffff16620927c08a602001518a8a8a888151811061086457fe5b602002602001015160405160240161087e939291906143a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161090791906140b9565b6000604051808303818686fa925050503d8060008114610943576040519150601f19603f3d011682016040523d82523d6000602084013e610948565b606091505b50909250905060008215610971578180602001905161096a9190810190613d6e565b9050610979565b50505061099c565b8086858151811061098657fe5b6020908102919091010152505050600101610826565b5050949350505050565b60606109b28385611fee565b81516040805182815260208084028201019091528180156109dd578160200160208202803883390190505b50915060005b81811015610b7957600060606109f76123ae565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a8881518110610a4157fe5b6020026020010151604051602401610a5b939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610ae491906140b9565b6000604051808303818686fa925050503d8060008114610b20576040519150601f19603f3d011682016040523d82523d6000602084013e610b25565b606091505b50909250905060008215610b4e5781806020019051610b479190810190613d6e565b9050610b56565b505050610b79565b80868581518110610b6357fe5b60209081029190910101525050506001016109e3565b50509392505050565b6060610b8e8385611fee565b8151604080518281526020808402820101909152818015610bb9578160200160208202803883390190505b5091506000610bc66123c6565b90506000805b83811015610caa578273ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161480610c3957508273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16145b15610c6357610c5c8888888481518110610c4f57fe5b60200260200101516123de565b9150610c8a565b610c748884888481518110610c4f57fe5b91508115610c8a57610c878388846123de565b91505b81858281518110610c9757fe5b6020908102919091010152600101610bcc565b505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610d1c57508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610d2657610d44565b6060610d33868585611001565b9050610d40848683611001565b9150505b949350505050565b6060610d588385611fee565b8151604080518281526020808402820101909152818015610d83578160200160208202803883390190505b5091506000610d906123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610dd057610dcb86612bfe565b610dd3565b60005b90506000610ddf6123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610e1f57610e1a86612bfe565b610e22565b60005b905060005b83811015610caa576001610e396123c6565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610ed0578651610eaf9085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b6020026020010151612c90565b878481518110610ebb57fe5b60200260200101819350828152505050610fed565b610ed86123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610f41578651610eaf9084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b8651600090610f7a9085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610ea257fe5b925090508015610fd057610faf857f2640f62c0000000000000000000000000000000000000000000000000000000083612c90565b888581518110610fbb57fe5b60200260200101819450828152505050610feb565b6000878481518110610fde57fe5b6020026020010181815250505b505b80610ff85750610caa565b50600101610e27565b606061100d8385611fee565b8151604080518281526020808402820101909152818015611038578160200160208202803883390190505b50915060005b81811015610b7957600060606110526123ae565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a888151811061109c57fe5b60200260200101516040516024016110b6939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161113f91906140b9565b6000604051808303818686fa925050503d806000811461117b576040519150601f19603f3d011682016040523d82523d6000602084013e611180565b606091505b50909250905060008215610b4e57818060200190516111a29190810190613d6e565b9050808685815181106111b157fe5b602090810291909101015250505060010161103e565b6040805182815260208084028201019091526060908280156111fd57816020015b60608152602001906001900390816111e85790505b50905060005b80831461130657600060603086868581811061121b57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13684900301811261125557600080fd5b9091016020810191503567ffffffffffffffff81111561127457600080fd5b3681900382131561128457600080fd5b6040516112929291906140a9565b600060405180830381855afa9150503d80600081146112cd576040519150601f19603f3d011682016040523d82523d6000602084013e6112d2565b606091505b5091509150816112e457805160208201fd5b808484815181106112f157fe5b60209081029190910101525050600101611203565b5092915050565b60606113198385611fee565b8151604080518281526020808402820101909152818015611344578160200160208202803883390190505b50915060006113516123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146113915761138c86612bfe565b611394565b60005b905060006113a06123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146113e0576113db86612bfe565b6113e3565b60005b905060005b83811015610caa5760016113fa6123c6565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156114845786516114639085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b87848151811061146f57fe5b602002602001018193508281525050506115a1565b61148c6123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156114f55786516114639084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b865160009061152e9086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610ea257fe5b92509050801561158457611563847fcd7724c30000000000000000000000000000000000000000000000000000000083612c90565b88858151811061156f57fe5b6020026020010181945082815250505061159f565b600087848151811061159257fe5b6020026020010181815250505b505b806115ac5750610caa565b506001016113e8565b60408401516060907fffffffff000000000000000000000000000000000000000000000000000000001661164f57604080516060810190915261164890806116018689608084016143bf565b604051602081830303815290604052815260200186886040516020016116289291906143bf565b6040516020818303038152906040528152602001612dd9815250836121d9565b9050610d44565b815160408051828152602080840282010190915281801561167a578160200160208202803883390190505b50915060005b8181101561099c5760006060886000015173ffffffffffffffffffffffffffffffffffffffff16620927c08a604001518a8a8a88815181106116be57fe5b60200260200101516040516024016116d8939291906143a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161176191906140b9565b6000604051808303818686fa925050503d806000811461179d576040519150601f19603f3d011682016040523d82523d6000602084013e6117a2565b606091505b5090925090506000821561097157818060200190516117c49190810190613d6e565b9050808685815181106117d357fe5b6020908102919091010152505050600101611680565b60606000825190508060405190808252806020026020018201604052801561181b578160200160208202803883390190505b509150600061182b878787611c3e565b905073ffffffffffffffffffffffffffffffffffffffff81166118505750610d449050565b60005b828110156119e257600060608373ffffffffffffffffffffffffffffffffffffffff1662061a80600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b88815181106118aa57fe5b60200260200101516040516024016118c4939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161194d91906140b9565b6000604051808303818686fa925050503d8060008114611989576040519150601f19603f3d011682016040523d82523d6000602084013e61198e565b606091505b509092509050600082156119b757818060200190516119b09190810190613d6e565b90506119bf565b5050506119e2565b808785815181106119cc57fe5b6020908102919091010152505050600101611853565b505050949350505050565b6040805160608181019092526105289080611a0c86896080840161412f565b60405160208183030381529060405281526020018688604051602001611a3392919061412f565b6040516020818303038152906040528152602001612f70815250836121d9565b606060008251905080604051908082528060200260200182016040528015611a85578160200160208202803883390190505b50915060005b81811015611c365760006060611a9f612fea565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff1663d06ca61f905060e01b888681518110611ae757fe5b60200260200101518a604051602401611b019291906145b8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611b8a91906140b9565b6000604051808303818686fa925050503d8060008114611bc6576040519150601f19603f3d011682016040523d82523d6000602084013e611bcb565b606091505b50909250905060008215611c0b5781806020019051611bed9190810190613a5c565b600189510381518110611bfc57fe5b60200260200101519050611c13565b505050611c36565b80868581518110611c2057fe5b6020908102919091010152505050600101611a8b565b505092915050565b6040516000906060907f153f59970000000000000000000000000000000000000000000000000000000090611c79908690869060240161412f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff1683604051611d0191906140b9565b600060405180830381855afa9150503d8060008114611d3c576040519150601f19603f3d011682016040523d82523d6000602084013e611d41565b606091505b5091509150818015611d54575080516020145b15611d6e57611d6481600c613002565b9350505050610334565b5050509392505050565b606060008251905080604051908082528060200260200182016040528015611daa578160200160208202803883390190505b50915060005b81811015611c365760006060611dc4612fea565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff16631f00ca74905060e01b888681518110611e0c57fe5b60200260200101518a604051602401611e269291906145b8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611eaf91906140b9565b6000604051808303818686fa925050503d8060008114611eeb576040519150601f19603f3d011682016040523d82523d6000602084013e611ef0565b606091505b50909250905060008215611c0b5781806020019051611f129190810190613a5c565b600081518110611f1e57fe5b6020026020010151905080868581518110611f3557fe5b6020908102919091010152505050600101611db0565b6060611f58848484610531565b905060005b84518110156107e657818181518110611f7257fe5b6020026020010151600014611fe657611fcd828281518110611f9057fe5b6020026020010151868381518110611fa457fe5b602002602001015160a00151878481518110611fbc57fe5b602002602001015160800151613047565b828281518110611fd957fe5b6020026020010181815250505b600101611f5d565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561205d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612054906143d7565b60405180910390fd5b5050565b60008060603073ffffffffffffffffffffffffffffffffffffffff16634cb8e25360e01b8780602001905161209991908101906136a1565b878060200190516120ad91908101906136a1565b6120b688613089565b6040516024016120c8939291906140f6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161215191906140b9565b600060405180830381855afa9150503d806000811461218c576040519150601f19603f3d011682016040523d82523d6000602084013e612191565b606091505b5091509150816121a657600092505050610334565b808060200190516121ba9190810190613a5c565b6000815181106121c657fe5b6020026020010151925050509392505050565b60608151604051908082528060200260200182016040528015612206578160200160208202803883390190505b509050815160001415612218576123a8565b6000612249846000015185602001518560008151811061223457fe5b6020026020010151876040015163ffffffff16565b90508061225657506123a8565b60006122738560200151866000015184886040015163ffffffff16565b90508061228257506123a89050565b60005b84518110156123a45760005b6005811015612366576122b88683815181106122a957fe5b60200260200101518486613047565b93506122c961271561271086613047565b935060006122e888602001518960000151878b6040015163ffffffff16565b9050806122f55750612366565b80935086838151811061230457fe5b6020026020010151841061235d57600087848151811061232057fe5b602002602001015161271089868151811061233757fe5b60200260200101518703028161234957fe5b0490506005811161235b575050612366565b505b50600101612291565b5061238585828151811061237657fe5b60200260200101518385613047565b84828151811061239157fe5b6020908102919091010152600101612285565b5050505b92915050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b60008060006123eb6130ca565b9150915060608173ffffffffffffffffffffffffffffffffffffffff16633d3dc52c6124156123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161461244d578861244f565b875b6040518263ffffffff1660e01b815260040161246b91906140d5565b60006040518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526124dd9190810190613a5c565b604080516000808252602082019092529192505b8251811015612796576040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b90612560907331e085afd48a1d6e51cc193153d625e8f0514c7f906004016140d5565b60206040518083038186803b15801561257857600080fd5b505afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506125b09190810190613d6e565b8382815181106125bc57fe5b6020026020010151148061269757506040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b90612631907310908c875d865c66f271f5d3949848971c9595c9906004016140d5565b60206040518083038186803b15801561264957600080fd5b505afa15801561265d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126819190810190613d6e565b83828151811061268d57fe5b6020026020010151145b8061276957506040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b9061270390731e158c0e93c30d24e918ef83d1e0be23595c3c0f906004016140d5565b60206040518083038186803b15801561271b57600080fd5b505afa15801561272f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127539190810190613d6e565b83828151811061275f57fe5b6020026020010151145b1561278e5761278b8284838151811061277e57fe5b60200260200101516131fe565b91505b6001016124f1565b5060606127a16123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128b8578473ffffffffffffffffffffffffffffffffffffffff166381efcbdd89600285600060405190808252806020026020018201604052801561281f578160200160208202803883390190505b506040518563ffffffff1660e01b815260040161283f949392919061425c565b60006040518083038186803b15801561285757600080fd5b505afa15801561286b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526128b19190810190613d86565b9050612998565b8473ffffffffffffffffffffffffffffffffffffffff166381efcbdd8a6002856000604051908082528060200260200182016040528015612903578160200160208202803883390190505b506040518563ffffffff1660e01b8152600401612923949392919061425c565b60006040518083038186803b15801561293b57600080fd5b505afa15801561294f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526129959190810190613d86565b90505b600060606129a4613294565b73ffffffffffffffffffffffffffffffffffffffff166216e3607f418436bc000000000000000000000000000000000000000000000000000000006129e76123c6565b73ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff1614612a1f578d612a35565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b612a3d6123c6565b73ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff1614612a75578d612a8b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b8d600089604051602401612aa3959493929190614209565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612b2c91906140b9565b6000604051808303818686fa925050503d8060008114612b68576040519150601f19603f3d011682016040523d82523d6000602084013e612b6d565b606091505b50909250905060008215612b965781806020019051612b8f9190810190613d6e565b9050612ba7565b600098505050505050505050610334565b6000612bb28c6132ac565b60ff1690506000612bc28e6132ac565b60ff169050670de0b6b3a764000081600a0a83600a0a8e86020281612be357fe5b0481612beb57fe5b049e9d5050505050505050505050505050565b6000612c086132b7565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b8152600401612c4091906140d5565b60206040518083038186803b158015612c5857600080fd5b505afa158015612c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123a891908101906136a1565b60008073ffffffffffffffffffffffffffffffffffffffff8516612cb357612dd1565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f08686604051602401612ce291906145af565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612d6b91906140b9565b6000604051808303818686fa925050503d8060008114612da7576040519150601f19603f3d011682016040523d82523d6000602084013e612dac565b606091505b5090925090508115612dcf5780806020019051612dcc9190810190613d6e565b92505b505b935093915050565b600080612de4613555565b85806020019051612df89190810190613e0f565b91509150600085806020019051612e129190810190613df3565b905060006060307f40bc03ae00000000000000000000000000000000000000000000000000000000858786612e468c613089565b604051602401612e599493929190614434565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612ee291906140b9565b600060405180830381855afa9150503d8060008114612f1d576040519150601f19603f3d011682016040523d82523d6000602084013e612f22565b606091505b509150915081612f3a57600095505050505050610334565b80806020019051612f4e9190810190613a5c565b600081518110612f5a57fe5b6020026020010151955050505050509392505050565b600080600085806020019051612f8991908101906136bd565b91509150600085806020019051612fa391908101906136a1565b905060006060307f9f76ad3500000000000000000000000000000000000000000000000000000000858786612fd78c613089565b604051602401612e599493929190614156565b73f164fc0ec4e93095b804a4795bbe1e041497b92a90565b600081601401835110156130285761302861302360048551856014016132cf565b613374565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006103318361307d61306182600163ffffffff61337c16565b613071888763ffffffff61339b16565b9063ffffffff6133cc16565b9063ffffffff6133e816565b6040805160018082528183019092526060916020808301908038833901905050905081816000815181106130b957fe5b602002602001018181525050919050565b6000806130d5613294565b73ffffffffffffffffffffffffffffffffffffffff1663b78b842d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561311a57600080fd5b505afa15801561312e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061315291908101906136a1565b73ffffffffffffffffffffffffffffffffffffffff1663c3a2a93a6040518163ffffffff1660e01b815260040160006040518083038186803b15801561319757600080fd5b505afa1580156131ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526131f19190810190613899565b5091955093505050509091565b6060825160010160405190808252806020026020018201604052801561322e578160200160208202803883390190505b50905060005b83518110156132705783818151811061324957fe5b602002602001015182828151811061325d57fe5b6020908102919091010152600101613234565b50818160018351038151811061328257fe5b60200260200101818152505092915050565b739aab3f75489902f3a48495025729a0af77d4b11e90565b60006123a882613412565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b6060632800659560e01b8484846040516024016132ee93929190614393565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b60008282111561339557613395613023600285856134e3565b50900390565b6000826133aa575060006123a8565b828202828482816133b757fe5b041461033457610334613023600186866134e3565b60008282018381101561033457610334613023600086866134e3565b6000816133fe576133fe613023600385856134e3565b600082848161340957fe5b04949350505050565b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce5670000000000000000000000000000000000000000000000000000000081525060405161347691906140b9565b600060405180830381855afa9150503d80600081146134b1576040519150601f19603f3d011682016040523d82523d6000602084013e6134b6565b606091505b50915091508180156134c9575080516020145b156134dc576134d9816000613502565b92505b5050919050565b606063e946c1bb60e01b8484846040516024016132ee93929190614372565b600061033483836000816020018351101561352a5761352a61302360058551856020016132cf565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b604080516060810182526000808252602082018190529181019190915290565b80356123a8816146e2565b600082601f830112613590578081fd5b81356135a361359e82614643565b61461c565b8181529150602080830190840160005b838110156135e0576135cb8760208435890101613653565b835260209283019291909101906001016135b3565b5050505092915050565b600082601f8301126135fa578081fd5b813561360861359e82614643565b81815291506020808301908481018184028601820187101561362957600080fd5b60005b848110156136485781358452928201929082019060010161362c565b505050505092915050565b600082601f830112613663578081fd5b813561367161359e82614663565b915080825283602082850101111561368857600080fd5b8060208401602084013760009082016020015292915050565b6000602082840312156136b2578081fd5b8151610334816146e2565b600080604083850312156136cf578081fd5b82516136da816146e2565b60208401519092506136eb816146e2565b809150509250929050565b60008060006060848603121561370a578081fd5b8335613715816146e2565b92506020840135613725816146e2565b91506040840135613735816146e2565b809150509250925092565b600080600080600060a08688031215613757578283fd5b8535613762816146e2565b94506020860135613772816146e2565b93506040860135613782816146e2565b92506060860135613792816146e2565b9150608086013567ffffffffffffffff8111156137ad578182fd5b6137b9888289016135ea565b9150509295509295909350565b600080600080608085870312156137db578182fd5b84356137e6816146e2565b935060208501356137f6816146e2565b92506040850135613806816146e2565b9150606085013567ffffffffffffffff811115613821578182fd5b61382d878288016135ea565b91505092959194509250565b60008060006060848603121561384d578081fd5b8335613858816146e2565b92506020840135613868816146e2565b9150604084013567ffffffffffffffff811115613883578182fd5b61388f868287016135ea565b9150509250925092565b60008060008060008060c087890312156138b1578384fd5b86516138bc816146e2565b809650506020808801516138cf816146e2565b60408901519096506138e0816146e2565b60608901519095506138f1816146e2565b6080890151909450613902816146e2565b60a089015190935067ffffffffffffffff81111561391e578283fd5b8089018a601f82011261392f578384fd5b8051915061393f61359e83614643565b82815283810190828501858502840186018e101561395b578687fd5b8693505b84841015613986578051613972816146e2565b83526001939093019291850191850161395f565b5080955050505050509295509295509295565b600080604083850312156139ab578182fd5b823567ffffffffffffffff808211156139c2578384fd5b81850186601f8201126139d3578485fd5b803592506139e361359e84614643565b80848252602080830192508084018a828389028701011115613a03578889fd5b8894505b86851015613a2e578035613a1a816146e2565b845260019490940193928101928101613a07565b509096508701359350505080821115613a45578283fd5b50613a52858286016135ea565b9150509250929050565b60006020808385031215613a6e578182fd5b825167ffffffffffffffff811115613a84578283fd5b80840185601f820112613a95578384fd5b80519150613aa561359e83614643565b8281528381019082850185850284018601891015613ac1578687fd5b8693505b84841015613ae3578051835260019390930192918501918501613ac5565b50979650505050505050565b60008060208385031215613b01578182fd5b823567ffffffffffffffff80821115613b18578384fd5b81850186601f820112613b29578485fd5b8035925081831115613b39578485fd5b8660208085028301011115613b4c578485fd5b60200196919550909350505050565b600080600060608486031215613b6f578081fd5b67ffffffffffffffff8085351115613b85578182fd5b8435850186601f820112613b97578283fd5b613ba461359e8235614643565b8135815260208082019190808401865b8535811015613d3157813586016101c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f03011215613bf3578889fd5b613bfe6101c061461c565b613c0a8e868401613575565b8152613c198e60408401613575565b85820152613c2a8e60608401613575565b6040820152613c3c8e60808401613575565b606082015260a0820135608082015260c082013560a082015260e082013560c082015261010082013560e082015261012082013561010082015261014082013561012082015261016082013589811115613c94578a8bfd5b613ca28f8783860101613653565b6101408301525061018082013589811115613cbb578a8bfd5b613cc98f8783860101613653565b610160830152506101a082013589811115613ce2578a8bfd5b613cf08f8783860101613653565b610180830152506101c082013589811115613d09578a8bfd5b613d178f8783860101613653565b6101a0830152508652509382019390820190600101613bb4565b509197508801359250505081811115613d48578283fd5b613d5487828801613580565b93505050613d658560408601613575565b90509250925092565b600060208284031215613d7f578081fd5b5051919050565b600060208284031215613d97578081fd5b815167ffffffffffffffff811115613dad578182fd5b80830184601f820112613dbe578283fd5b80519150613dce61359e83614663565b828152856020848401011115613de2578384fd5b6105288360208301602085016146a5565b600060208284031215613e04578081fd5b815161033481614732565b60008060808385031215613e21578182fd5b8251613e2c81614732565b915060608385037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613e5f578081fd5b613e69606061461c565b6020840151613e77816146e2565b81526040840151613e8781614704565b60208201526060840151613e9a81614704565b6040820152919491935090915050565b60008060008084860360c0811215613ec0578283fd5b6060811215613ecd578283fd5b50613ed8606061461c565b8535613ee3816146e2565b81526020860135613ef381614704565b60208201526040860135613f0681614704565b604082015293506060850135613f1b81614732565b92506080850135613f2b81614732565b915060a085013567ffffffffffffffff811115613821578182fd5b600080600083850360a0811215613f5b578182fd5b6060811215613f68578182fd5b50613f73606061461c565b845160078110613f81578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114613735578182fd5b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b82811015613ffe578151865260209586019590910190600101613fe0565b5093949350505050565b600081518084526140208160208601602086016146a5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff1682526020808201517fffffffff000000000000000000000000000000000000000000000000000000009081169184019190915260409182015116910152565b6000828483379101908152919050565b600082516140cb8184602087016146a5565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526105286060830184613fcd565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526141976080830184613fcd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260ff8416606083015260a0608083015261425160a0830184614008565b979650505050505050565b60006080820173ffffffffffffffffffffffffffffffffffffffff87168352614284866146d5565b60208381018790526080604085015285519182905285019060a0840190835b818110156142c15783518352602093840193909201916001016142a3565b505083810360608501526142d58186613fcd565b98975050505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015614352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614340858351614008565b94509285019290850190600101614306565b5092979650505050505050565b6000602082526103346020830184613fcd565b6060810161437f856146d5565b938152602081019290925260409091015290565b606081016008851061437f57fe5b600f93840b81529190920b6020820152604081019190915260600190565b600f83900b8152608081016103346020830184614052565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b60006144408287614052565b84600f0b606083015283600f0b608083015260c060a083015261419760c0830184613fcd565b60006040825261447a604083018551613fb3565b602084015161448c6060840182613fb3565b50604084015161449f6080840182613fb3565b5060608401516144b260a0840182613fb3565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c091506101808281870152614523610200870185614008565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a08388830301818901526145628287614008565b838b015196508489820301868a015261457b8188614008565b955050808a0151955050505080858303016101e08601525061459d8183614008565b84810360208601526142518187614008565b90815260200190565b60006040820184835260406020840152808451808352606085019150602086019250835b8181101561461057835173ffffffffffffffffffffffffffffffffffffffff168352602093840193909201916001016145dc565b50909695505050505050565b60405181810167ffffffffffffffff8111828210171561463b57600080fd5b604052919050565b600067ffffffffffffffff821115614659578081fd5b5060209081020190565b600067ffffffffffffffff821115614679578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110156146c05781810151838201526020016146a8565b838111156146cf576000848401525b50505050565b600481106146df57fe5b50565b73ffffffffffffffffffffffffffffffffffffffff811681146146df57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000811681146146df57600080fd5b80600f0b81146146df57600080fdfea365627a7a72315820b6fbcf4008958c944ebfec299da165bd697cf68b9711b57b06ab81852a3933ff6c6578706572696d656e74616cf564736f6c63430005110040" - }, - "deployedBytecode": { - "object": "0x608060405234801561001057600080fd5b50600436106101365760003560e01c806368be3cf2116100b2578063a2c28d4b11610081578063c7f7142e11610066578063c7f7142e1461027b578063e68248f71461029b578063e9a8e442146102ae57610136565b8063a2c28d4b14610255578063abffc7611461026857610136565b806368be3cf2146101fc5780636dd6b78d1461021c5780639209483b1461022f5780639f76ad351461024257610136565b80634703a7e61161010957806358306ba0116100ee57806358306ba0146101c357806360ee052a146101d657806364ee6ade146101e957610136565b80634703a7e61461019d5780634cb8e253146101b057610136565b80630cc6600b1461013b5780632d753aa41461016457806339b085ad1461017757806340bc03ae1461018a575b600080fd5b61014e610149366004613839565b6102c1565b60405161015b919061435f565b60405180910390f35b61014e610172366004613740565b61033b565b61014e610185366004613b5b565b610531565b61014e610198366004613eaa565b6107ee565b61014e6101ab366004613839565b6109a6565b61014e6101be366004613839565b610b82565b61014e6101d13660046137c6565b610cb5565b61014e6101e4366004613839565b610d4c565b61014e6101f7366004613839565b611001565b61020f61020a366004613aef565b6111c7565b60405161015b91906142e1565b61014e61022a366004613839565b61130d565b61014e61023d366004613eaa565b6115b5565b61014e6102503660046137c6565b6117e9565b61014e6102633660046137c6565b6119ed565b61014e610276366004613999565b611a53565b61028e6102893660046136f6565b611c3e565b60405161015b91906140d5565b61014e6102a9366004613999565b611d78565b61014e6102bc366004613b5b565b611f4b565b60606102cd8385611fee565b6103316040518060600160405280856040516020016102ec91906140d5565b60405160208183030381529060405281526020018660405160200161031191906140d5565b6040516020818303038152906040528152602001612061815250836121d9565b90505b9392505050565b60606000825190508060405190808252806020026020018201604052801561036d578160200160208202803883390190505b50915073ffffffffffffffffffffffffffffffffffffffff87166103915750610528565b60005b8181101561052557600060608973ffffffffffffffffffffffffffffffffffffffff1662061a80600073ffffffffffffffffffffffffffffffffffffffff16636e79e133905060e01b8b8b8b8b89815181106103ec57fe5b602002602001015160405160240161040794939291906141a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161049091906140b9565b6000604051808303818686fa925050503d80600081146104cc576040519150601f19603f3d011682016040523d82523d6000602084013e6104d1565b606091505b509092509050600082156104fa57818060200190516104f39190810190613d6e565b9050610502565b505050610525565b8086858151811061050f57fe5b6020908102919091010152505050600101610394565b50505b95945050505050565b6060835160405190808252806020026020018201604052801561055e578160200160208202803883390190505b50905060005b845181146107e65783818151811061057857fe5b602002602001015151600014806105a6575084818151811061059657fe5b6020026020010151608001516000145b806105c857508481815181106105b857fe5b602002602001015160a001516000145b156105ec5760008282815181106105db57fe5b6020026020010181815250506107de565b600060608473ffffffffffffffffffffffffffffffffffffffff166207a1208673ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b89868151811061063857fe5b602002602001015189878151811061064c57fe5b6020026020010151604051602401610665929190614466565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516106ee91906140b9565b6000604051808303818686fa925050503d806000811461072a576040519150601f19603f3d011682016040523d82523d6000602084013e61072f565b606091505b50915091508161075a57600084848151811061074757fe5b60200260200101818152505050506107de565b610762613533565b600080838060200190516107799190810190613f46565b9194509250905060038351600681111561078f57fe5b14158061079a575080155b156107be5760008787815181106107ad57fe5b6020026020010181815250506107d8565b818787815181106107cb57fe5b6020026020010181815250505b50505050505b600101610564565b509392505050565b606060008251905080604051908082528060200260200182016040528015610820578160200160208202803883390190505b50915060005b8181101561099c5760006060886000015173ffffffffffffffffffffffffffffffffffffffff16620927c08a602001518a8a8a888151811061086457fe5b602002602001015160405160240161087e939291906143a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161090791906140b9565b6000604051808303818686fa925050503d8060008114610943576040519150601f19603f3d011682016040523d82523d6000602084013e610948565b606091505b50909250905060008215610971578180602001905161096a9190810190613d6e565b9050610979565b50505061099c565b8086858151811061098657fe5b6020908102919091010152505050600101610826565b5050949350505050565b60606109b28385611fee565b81516040805182815260208084028201019091528180156109dd578160200160208202803883390190505b50915060005b81811015610b7957600060606109f76123ae565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a8881518110610a4157fe5b6020026020010151604051602401610a5b939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610ae491906140b9565b6000604051808303818686fa925050503d8060008114610b20576040519150601f19603f3d011682016040523d82523d6000602084013e610b25565b606091505b50909250905060008215610b4e5781806020019051610b479190810190613d6e565b9050610b56565b505050610b79565b80868581518110610b6357fe5b60209081029190910101525050506001016109e3565b50509392505050565b6060610b8e8385611fee565b8151604080518281526020808402820101909152818015610bb9578160200160208202803883390190505b5091506000610bc66123c6565b90506000805b83811015610caa578273ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161480610c3957508273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16145b15610c6357610c5c8888888481518110610c4f57fe5b60200260200101516123de565b9150610c8a565b610c748884888481518110610c4f57fe5b91508115610c8a57610c878388846123de565b91505b81858281518110610c9757fe5b6020908102919091010152600101610bcc565b505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610d1c57508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610d2657610d44565b6060610d33868585611001565b9050610d40848683611001565b9150505b949350505050565b6060610d588385611fee565b8151604080518281526020808402820101909152818015610d83578160200160208202803883390190505b5091506000610d906123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610dd057610dcb86612bfe565b610dd3565b60005b90506000610ddf6123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610e1f57610e1a86612bfe565b610e22565b60005b905060005b83811015610caa576001610e396123c6565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610ed0578651610eaf9085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b6020026020010151612c90565b878481518110610ebb57fe5b60200260200101819350828152505050610fed565b610ed86123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610f41578651610eaf9084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b8651600090610f7a9085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610ea257fe5b925090508015610fd057610faf857f2640f62c0000000000000000000000000000000000000000000000000000000083612c90565b888581518110610fbb57fe5b60200260200101819450828152505050610feb565b6000878481518110610fde57fe5b6020026020010181815250505b505b80610ff85750610caa565b50600101610e27565b606061100d8385611fee565b8151604080518281526020808402820101909152818015611038578160200160208202803883390190505b50915060005b81811015610b7957600060606110526123ae565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a888151811061109c57fe5b60200260200101516040516024016110b6939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161113f91906140b9565b6000604051808303818686fa925050503d806000811461117b576040519150601f19603f3d011682016040523d82523d6000602084013e611180565b606091505b50909250905060008215610b4e57818060200190516111a29190810190613d6e565b9050808685815181106111b157fe5b602090810291909101015250505060010161103e565b6040805182815260208084028201019091526060908280156111fd57816020015b60608152602001906001900390816111e85790505b50905060005b80831461130657600060603086868581811061121b57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13684900301811261125557600080fd5b9091016020810191503567ffffffffffffffff81111561127457600080fd5b3681900382131561128457600080fd5b6040516112929291906140a9565b600060405180830381855afa9150503d80600081146112cd576040519150601f19603f3d011682016040523d82523d6000602084013e6112d2565b606091505b5091509150816112e457805160208201fd5b808484815181106112f157fe5b60209081029190910101525050600101611203565b5092915050565b60606113198385611fee565b8151604080518281526020808402820101909152818015611344578160200160208202803883390190505b50915060006113516123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146113915761138c86612bfe565b611394565b60005b905060006113a06123c6565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146113e0576113db86612bfe565b6113e3565b60005b905060005b83811015610caa5760016113fa6123c6565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156114845786516114639085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b87848151811061146f57fe5b602002602001018193508281525050506115a1565b61148c6123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156114f55786516114639084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610ea257fe5b865160009061152e9086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610ea257fe5b92509050801561158457611563847fcd7724c30000000000000000000000000000000000000000000000000000000083612c90565b88858151811061156f57fe5b6020026020010181945082815250505061159f565b600087848151811061159257fe5b6020026020010181815250505b505b806115ac5750610caa565b506001016113e8565b60408401516060907fffffffff000000000000000000000000000000000000000000000000000000001661164f57604080516060810190915261164890806116018689608084016143bf565b604051602081830303815290604052815260200186886040516020016116289291906143bf565b6040516020818303038152906040528152602001612dd9815250836121d9565b9050610d44565b815160408051828152602080840282010190915281801561167a578160200160208202803883390190505b50915060005b8181101561099c5760006060886000015173ffffffffffffffffffffffffffffffffffffffff16620927c08a604001518a8a8a88815181106116be57fe5b60200260200101516040516024016116d8939291906143a1565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161176191906140b9565b6000604051808303818686fa925050503d806000811461179d576040519150601f19603f3d011682016040523d82523d6000602084013e6117a2565b606091505b5090925090506000821561097157818060200190516117c49190810190613d6e565b9050808685815181106117d357fe5b6020908102919091010152505050600101611680565b60606000825190508060405190808252806020026020018201604052801561181b578160200160208202803883390190505b509150600061182b878787611c3e565b905073ffffffffffffffffffffffffffffffffffffffff81166118505750610d449050565b60005b828110156119e257600060608373ffffffffffffffffffffffffffffffffffffffff1662061a80600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b88815181106118aa57fe5b60200260200101516040516024016118c4939291906141d8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161194d91906140b9565b6000604051808303818686fa925050503d8060008114611989576040519150601f19603f3d011682016040523d82523d6000602084013e61198e565b606091505b509092509050600082156119b757818060200190516119b09190810190613d6e565b90506119bf565b5050506119e2565b808785815181106119cc57fe5b6020908102919091010152505050600101611853565b505050949350505050565b6040805160608181019092526105289080611a0c86896080840161412f565b60405160208183030381529060405281526020018688604051602001611a3392919061412f565b6040516020818303038152906040528152602001612f70815250836121d9565b606060008251905080604051908082528060200260200182016040528015611a85578160200160208202803883390190505b50915060005b81811015611c365760006060611a9f612fea565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff1663d06ca61f905060e01b888681518110611ae757fe5b60200260200101518a604051602401611b019291906145b8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611b8a91906140b9565b6000604051808303818686fa925050503d8060008114611bc6576040519150601f19603f3d011682016040523d82523d6000602084013e611bcb565b606091505b50909250905060008215611c0b5781806020019051611bed9190810190613a5c565b600189510381518110611bfc57fe5b60200260200101519050611c13565b505050611c36565b80868581518110611c2057fe5b6020908102919091010152505050600101611a8b565b505092915050565b6040516000906060907f153f59970000000000000000000000000000000000000000000000000000000090611c79908690869060240161412f565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff1683604051611d0191906140b9565b600060405180830381855afa9150503d8060008114611d3c576040519150601f19603f3d011682016040523d82523d6000602084013e611d41565b606091505b5091509150818015611d54575080516020145b15611d6e57611d6481600c613002565b9350505050610334565b5050509392505050565b606060008251905080604051908082528060200260200182016040528015611daa578160200160208202803883390190505b50915060005b81811015611c365760006060611dc4612fea565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff16631f00ca74905060e01b888681518110611e0c57fe5b60200260200101518a604051602401611e269291906145b8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611eaf91906140b9565b6000604051808303818686fa925050503d8060008114611eeb576040519150601f19603f3d011682016040523d82523d6000602084013e611ef0565b606091505b50909250905060008215611c0b5781806020019051611f129190810190613a5c565b600081518110611f1e57fe5b6020026020010151905080868581518110611f3557fe5b6020908102919091010152505050600101611db0565b6060611f58848484610531565b905060005b84518110156107e657818181518110611f7257fe5b6020026020010151600014611fe657611fcd828281518110611f9057fe5b6020026020010151868381518110611fa457fe5b602002602001015160a00151878481518110611fbc57fe5b602002602001015160800151613047565b828281518110611fd957fe5b6020026020010181815250505b600101611f5d565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561205d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612054906143d7565b60405180910390fd5b5050565b60008060603073ffffffffffffffffffffffffffffffffffffffff16634cb8e25360e01b8780602001905161209991908101906136a1565b878060200190516120ad91908101906136a1565b6120b688613089565b6040516024016120c8939291906140f6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161215191906140b9565b600060405180830381855afa9150503d806000811461218c576040519150601f19603f3d011682016040523d82523d6000602084013e612191565b606091505b5091509150816121a657600092505050610334565b808060200190516121ba9190810190613a5c565b6000815181106121c657fe5b6020026020010151925050509392505050565b60608151604051908082528060200260200182016040528015612206578160200160208202803883390190505b509050815160001415612218576123a8565b6000612249846000015185602001518560008151811061223457fe5b6020026020010151876040015163ffffffff16565b90508061225657506123a8565b60006122738560200151866000015184886040015163ffffffff16565b90508061228257506123a89050565b60005b84518110156123a45760005b6005811015612366576122b88683815181106122a957fe5b60200260200101518486613047565b93506122c961271561271086613047565b935060006122e888602001518960000151878b6040015163ffffffff16565b9050806122f55750612366565b80935086838151811061230457fe5b6020026020010151841061235d57600087848151811061232057fe5b602002602001015161271089868151811061233757fe5b60200260200101518703028161234957fe5b0490506005811161235b575050612366565b505b50600101612291565b5061238585828151811061237657fe5b60200260200101518385613047565b84828151811061239157fe5b6020908102919091010152600101612285565b5050505b92915050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b60008060006123eb6130ca565b9150915060608173ffffffffffffffffffffffffffffffffffffffff16633d3dc52c6124156123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161461244d578861244f565b875b6040518263ffffffff1660e01b815260040161246b91906140d5565b60006040518083038186803b15801561248357600080fd5b505afa158015612497573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526124dd9190810190613a5c565b604080516000808252602082019092529192505b8251811015612796576040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b90612560907331e085afd48a1d6e51cc193153d625e8f0514c7f906004016140d5565b60206040518083038186803b15801561257857600080fd5b505afa15801561258c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506125b09190810190613d6e565b8382815181106125bc57fe5b6020026020010151148061269757506040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b90612631907310908c875d865c66f271f5d3949848971c9595c9906004016140d5565b60206040518083038186803b15801561264957600080fd5b505afa15801561265d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126819190810190613d6e565b83828151811061268d57fe5b6020026020010151145b8061276957506040517f106e9a4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063106e9a4b9061270390731e158c0e93c30d24e918ef83d1e0be23595c3c0f906004016140d5565b60206040518083038186803b15801561271b57600080fd5b505afa15801561272f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127539190810190613d6e565b83828151811061275f57fe5b6020026020010151145b1561278e5761278b8284838151811061277e57fe5b60200260200101516131fe565b91505b6001016124f1565b5060606127a16123c6565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128b8578473ffffffffffffffffffffffffffffffffffffffff166381efcbdd89600285600060405190808252806020026020018201604052801561281f578160200160208202803883390190505b506040518563ffffffff1660e01b815260040161283f949392919061425c565b60006040518083038186803b15801561285757600080fd5b505afa15801561286b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526128b19190810190613d86565b9050612998565b8473ffffffffffffffffffffffffffffffffffffffff166381efcbdd8a6002856000604051908082528060200260200182016040528015612903578160200160208202803883390190505b506040518563ffffffff1660e01b8152600401612923949392919061425c565b60006040518083038186803b15801561293b57600080fd5b505afa15801561294f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526129959190810190613d86565b90505b600060606129a4613294565b73ffffffffffffffffffffffffffffffffffffffff166216e3607f418436bc000000000000000000000000000000000000000000000000000000006129e76123c6565b73ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff1614612a1f578d612a35565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b612a3d6123c6565b73ffffffffffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff1614612a75578d612a8b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b8d600089604051602401612aa3959493929190614209565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612b2c91906140b9565b6000604051808303818686fa925050503d8060008114612b68576040519150601f19603f3d011682016040523d82523d6000602084013e612b6d565b606091505b50909250905060008215612b965781806020019051612b8f9190810190613d6e565b9050612ba7565b600098505050505050505050610334565b6000612bb28c6132ac565b60ff1690506000612bc28e6132ac565b60ff169050670de0b6b3a764000081600a0a83600a0a8e86020281612be357fe5b0481612beb57fe5b049e9d5050505050505050505050505050565b6000612c086132b7565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b8152600401612c4091906140d5565b60206040518083038186803b158015612c5857600080fd5b505afa158015612c6c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506123a891908101906136a1565b60008073ffffffffffffffffffffffffffffffffffffffff8516612cb357612dd1565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f08686604051602401612ce291906145af565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612d6b91906140b9565b6000604051808303818686fa925050503d8060008114612da7576040519150601f19603f3d011682016040523d82523d6000602084013e612dac565b606091505b5090925090508115612dcf5780806020019051612dcc9190810190613d6e565b92505b505b935093915050565b600080612de4613555565b85806020019051612df89190810190613e0f565b91509150600085806020019051612e129190810190613df3565b905060006060307f40bc03ae00000000000000000000000000000000000000000000000000000000858786612e468c613089565b604051602401612e599493929190614434565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612ee291906140b9565b600060405180830381855afa9150503d8060008114612f1d576040519150601f19603f3d011682016040523d82523d6000602084013e612f22565b606091505b509150915081612f3a57600095505050505050610334565b80806020019051612f4e9190810190613a5c565b600081518110612f5a57fe5b6020026020010151955050505050509392505050565b600080600085806020019051612f8991908101906136bd565b91509150600085806020019051612fa391908101906136a1565b905060006060307f9f76ad3500000000000000000000000000000000000000000000000000000000858786612fd78c613089565b604051602401612e599493929190614156565b73f164fc0ec4e93095b804a4795bbe1e041497b92a90565b600081601401835110156130285761302861302360048551856014016132cf565b613374565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006103318361307d61306182600163ffffffff61337c16565b613071888763ffffffff61339b16565b9063ffffffff6133cc16565b9063ffffffff6133e816565b6040805160018082528183019092526060916020808301908038833901905050905081816000815181106130b957fe5b602002602001018181525050919050565b6000806130d5613294565b73ffffffffffffffffffffffffffffffffffffffff1663b78b842d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561311a57600080fd5b505afa15801561312e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061315291908101906136a1565b73ffffffffffffffffffffffffffffffffffffffff1663c3a2a93a6040518163ffffffff1660e01b815260040160006040518083038186803b15801561319757600080fd5b505afa1580156131ab573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526131f19190810190613899565b5091955093505050509091565b6060825160010160405190808252806020026020018201604052801561322e578160200160208202803883390190505b50905060005b83518110156132705783818151811061324957fe5b602002602001015182828151811061325d57fe5b6020908102919091010152600101613234565b50818160018351038151811061328257fe5b60200260200101818152505092915050565b739aab3f75489902f3a48495025729a0af77d4b11e90565b60006123a882613412565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b6060632800659560e01b8484846040516024016132ee93929190614393565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b60008282111561339557613395613023600285856134e3565b50900390565b6000826133aa575060006123a8565b828202828482816133b757fe5b041461033457610334613023600186866134e3565b60008282018381101561033457610334613023600086866134e3565b6000816133fe576133fe613023600385856134e3565b600082848161340957fe5b04949350505050565b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce5670000000000000000000000000000000000000000000000000000000081525060405161347691906140b9565b600060405180830381855afa9150503d80600081146134b1576040519150601f19603f3d011682016040523d82523d6000602084013e6134b6565b606091505b50915091508180156134c9575080516020145b156134dc576134d9816000613502565b92505b5050919050565b606063e946c1bb60e01b8484846040516024016132ee93929190614372565b600061033483836000816020018351101561352a5761352a61302360058551856020016132cf565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b604080516060810182526000808252602082018190529181019190915290565b80356123a8816146e2565b600082601f830112613590578081fd5b81356135a361359e82614643565b61461c565b8181529150602080830190840160005b838110156135e0576135cb8760208435890101613653565b835260209283019291909101906001016135b3565b5050505092915050565b600082601f8301126135fa578081fd5b813561360861359e82614643565b81815291506020808301908481018184028601820187101561362957600080fd5b60005b848110156136485781358452928201929082019060010161362c565b505050505092915050565b600082601f830112613663578081fd5b813561367161359e82614663565b915080825283602082850101111561368857600080fd5b8060208401602084013760009082016020015292915050565b6000602082840312156136b2578081fd5b8151610334816146e2565b600080604083850312156136cf578081fd5b82516136da816146e2565b60208401519092506136eb816146e2565b809150509250929050565b60008060006060848603121561370a578081fd5b8335613715816146e2565b92506020840135613725816146e2565b91506040840135613735816146e2565b809150509250925092565b600080600080600060a08688031215613757578283fd5b8535613762816146e2565b94506020860135613772816146e2565b93506040860135613782816146e2565b92506060860135613792816146e2565b9150608086013567ffffffffffffffff8111156137ad578182fd5b6137b9888289016135ea565b9150509295509295909350565b600080600080608085870312156137db578182fd5b84356137e6816146e2565b935060208501356137f6816146e2565b92506040850135613806816146e2565b9150606085013567ffffffffffffffff811115613821578182fd5b61382d878288016135ea565b91505092959194509250565b60008060006060848603121561384d578081fd5b8335613858816146e2565b92506020840135613868816146e2565b9150604084013567ffffffffffffffff811115613883578182fd5b61388f868287016135ea565b9150509250925092565b60008060008060008060c087890312156138b1578384fd5b86516138bc816146e2565b809650506020808801516138cf816146e2565b60408901519096506138e0816146e2565b60608901519095506138f1816146e2565b6080890151909450613902816146e2565b60a089015190935067ffffffffffffffff81111561391e578283fd5b8089018a601f82011261392f578384fd5b8051915061393f61359e83614643565b82815283810190828501858502840186018e101561395b578687fd5b8693505b84841015613986578051613972816146e2565b83526001939093019291850191850161395f565b5080955050505050509295509295509295565b600080604083850312156139ab578182fd5b823567ffffffffffffffff808211156139c2578384fd5b81850186601f8201126139d3578485fd5b803592506139e361359e84614643565b80848252602080830192508084018a828389028701011115613a03578889fd5b8894505b86851015613a2e578035613a1a816146e2565b845260019490940193928101928101613a07565b509096508701359350505080821115613a45578283fd5b50613a52858286016135ea565b9150509250929050565b60006020808385031215613a6e578182fd5b825167ffffffffffffffff811115613a84578283fd5b80840185601f820112613a95578384fd5b80519150613aa561359e83614643565b8281528381019082850185850284018601891015613ac1578687fd5b8693505b84841015613ae3578051835260019390930192918501918501613ac5565b50979650505050505050565b60008060208385031215613b01578182fd5b823567ffffffffffffffff80821115613b18578384fd5b81850186601f820112613b29578485fd5b8035925081831115613b39578485fd5b8660208085028301011115613b4c578485fd5b60200196919550909350505050565b600080600060608486031215613b6f578081fd5b67ffffffffffffffff8085351115613b85578182fd5b8435850186601f820112613b97578283fd5b613ba461359e8235614643565b8135815260208082019190808401865b8535811015613d3157813586016101c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f03011215613bf3578889fd5b613bfe6101c061461c565b613c0a8e868401613575565b8152613c198e60408401613575565b85820152613c2a8e60608401613575565b6040820152613c3c8e60808401613575565b606082015260a0820135608082015260c082013560a082015260e082013560c082015261010082013560e082015261012082013561010082015261014082013561012082015261016082013589811115613c94578a8bfd5b613ca28f8783860101613653565b6101408301525061018082013589811115613cbb578a8bfd5b613cc98f8783860101613653565b610160830152506101a082013589811115613ce2578a8bfd5b613cf08f8783860101613653565b610180830152506101c082013589811115613d09578a8bfd5b613d178f8783860101613653565b6101a0830152508652509382019390820190600101613bb4565b509197508801359250505081811115613d48578283fd5b613d5487828801613580565b93505050613d658560408601613575565b90509250925092565b600060208284031215613d7f578081fd5b5051919050565b600060208284031215613d97578081fd5b815167ffffffffffffffff811115613dad578182fd5b80830184601f820112613dbe578283fd5b80519150613dce61359e83614663565b828152856020848401011115613de2578384fd5b6105288360208301602085016146a5565b600060208284031215613e04578081fd5b815161033481614732565b60008060808385031215613e21578182fd5b8251613e2c81614732565b915060608385037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613e5f578081fd5b613e69606061461c565b6020840151613e77816146e2565b81526040840151613e8781614704565b60208201526060840151613e9a81614704565b6040820152919491935090915050565b60008060008084860360c0811215613ec0578283fd5b6060811215613ecd578283fd5b50613ed8606061461c565b8535613ee3816146e2565b81526020860135613ef381614704565b60208201526040860135613f0681614704565b604082015293506060850135613f1b81614732565b92506080850135613f2b81614732565b915060a085013567ffffffffffffffff811115613821578182fd5b600080600083850360a0811215613f5b578182fd5b6060811215613f68578182fd5b50613f73606061461c565b845160078110613f81578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114613735578182fd5b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b82811015613ffe578151865260209586019590910190600101613fe0565b5093949350505050565b600081518084526140208160208601602086016146a5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b805173ffffffffffffffffffffffffffffffffffffffff1682526020808201517fffffffff000000000000000000000000000000000000000000000000000000009081169184019190915260409182015116910152565b6000828483379101908152919050565b600082516140cb8184602087016146a5565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526105286060830184613fcd565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526141976080830184613fcd565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff9485168152928416602084015292166040820152606081019190915260800190565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b600073ffffffffffffffffffffffffffffffffffffffff808816835280871660208401525084604083015260ff8416606083015260a0608083015261425160a0830184614008565b979650505050505050565b60006080820173ffffffffffffffffffffffffffffffffffffffff87168352614284866146d5565b60208381018790526080604085015285519182905285019060a0840190835b818110156142c15783518352602093840193909201916001016142a3565b505083810360608501526142d58186613fcd565b98975050505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015614352577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614340858351614008565b94509285019290850190600101614306565b5092979650505050505050565b6000602082526103346020830184613fcd565b6060810161437f856146d5565b938152602081019290925260409091015290565b606081016008851061437f57fe5b600f93840b81529190920b6020820152604081019190915260600190565b600f83900b8152608081016103346020830184614052565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b60006144408287614052565b84600f0b606083015283600f0b608083015260c060a083015261419760c0830184613fcd565b60006040825261447a604083018551613fb3565b602084015161448c6060840182613fb3565b50604084015161449f6080840182613fb3565b5060608401516144b260a0840182613fb3565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c091506101808281870152614523610200870185614008565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a08388830301818901526145628287614008565b838b015196508489820301868a015261457b8188614008565b955050808a0151955050505080858303016101e08601525061459d8183614008565b84810360208601526142518187614008565b90815260200190565b60006040820184835260406020840152808451808352606085019150602086019250835b8181101561461057835173ffffffffffffffffffffffffffffffffffffffff168352602093840193909201916001016145dc565b50909695505050505050565b60405181810167ffffffffffffffff8111828210171561463b57600080fd5b604052919050565b600067ffffffffffffffff821115614659578081fd5b5060209081020190565b600067ffffffffffffffff821115614679578081fd5b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60005b838110156146c05781810151838201526020016146a8565b838111156146cf576000848401525b50505050565b600481106146df57fe5b50565b73ffffffffffffffffffffffffffffffffffffffff811681146146df57600080fd5b7fffffffff00000000000000000000000000000000000000000000000000000000811681146146df57600080fd5b80600f0b81146146df57600080fdfea365627a7a72315820b6fbcf4008958c944ebfec299da165bd697cf68b9711b57b06ab81852a3933ff6c6578706572696d656e74616cf564736f6c63430005110040" - } - } - }, - "compiler": { - "name": "solc", - "version": "0.5.17+commit.d19bba13", - "settings": { - "optimizer": { - "enabled": true, - "runs": 1000000, - "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true } - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "devdoc", - "evm.bytecode.object", - "evm.bytecode.sourceMap", - "evm.deployedBytecode.object", - "evm.deployedBytecode.sourceMap" - ] - } - }, - "evmVersion": "istanbul" - } - }, - "chains": {} -} diff --git a/packages/contract-artifacts/src/index.ts b/packages/contract-artifacts/src/index.ts index 85fd93702f..ae7f611786 100644 --- a/packages/contract-artifacts/src/index.ts +++ b/packages/contract-artifacts/src/index.ts @@ -8,7 +8,6 @@ import * as DummyERC721Token from '../artifacts/DummyERC721Token.json'; import * as ERC1155Mintable from '../artifacts/ERC1155Mintable.json'; import * as ERC1155Proxy from '../artifacts/ERC1155Proxy.json'; import * as ERC20BridgeProxy from '../artifacts/ERC20BridgeProxy.json'; -import * as ERC20BridgeSampler from '../artifacts/ERC20BridgeSampler.json'; import * as ERC20Proxy from '../artifacts/ERC20Proxy.json'; import * as ERC20Token from '../artifacts/ERC20Token.json'; import * as ERC721Proxy from '../artifacts/ERC721Proxy.json'; @@ -57,7 +56,6 @@ export { Staking, StakingProxy, ZrxVault, - ERC20BridgeSampler, ITransformERC20, IZeroEx, }; diff --git a/packages/contract-artifacts/tsconfig.json b/packages/contract-artifacts/tsconfig.json index c6c46edb63..3ee1d82c58 100644 --- a/packages/contract-artifacts/tsconfig.json +++ b/packages/contract-artifacts/tsconfig.json @@ -36,7 +36,6 @@ "./artifacts/StakingProxy.json", "./artifacts/ZrxVault.json", "./artifacts/ERC20BridgeProxy.json", - "./artifacts/ERC20BridgeSampler.json", "./artifacts/ITransformERC20.json", "./artifacts/IZeroEx.json" ] diff --git a/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts b/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts deleted file mode 100644 index 51c5475c18..0000000000 --- a/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts +++ /dev/null @@ -1,1631 +0,0 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming -// tslint:disable:whitespace no-unbound-method no-trailing-whitespace -// tslint:disable:no-unused-variable -import { - AwaitTransactionSuccessOpts, - ContractFunctionObj, - ContractTxFunctionObj, - SendTransactionOpts, - BaseContract, - PromiseWithTransactionHash, - methodAbiToFunctionSignature, - linkLibrariesInBytecode, -} from '@0x/base-contract'; -import { schemas } from '@0x/json-schemas'; -import { - BlockParam, - BlockParamLiteral, - BlockRange, - CallData, - ContractAbi, - ContractArtifact, - DecodedLogArgs, - MethodAbi, - TransactionReceiptWithDecodedLogs, - TxData, - TxDataPayable, - SupportedProvider, -} from 'ethereum-types'; -import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils'; -import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { assert } from '@0x/assert'; -import * as ethers from 'ethers'; -// tslint:enable:no-unused-variable - -/* istanbul ignore next */ -// tslint:disable:array-type -// tslint:disable:no-parameter-reassignment -// tslint:disable-next-line:class-name -export class ERC20BridgeSamplerContract extends BaseContract { - /** - * @ignore - */ - public static deployedBytecode: string | undefined; - public static contractName = 'ERC20BridgeSampler'; - private readonly _methodABIIndex: { [name: string]: number } = {}; - public static async deployFrom0xArtifactAsync( - artifact: ContractArtifact | SimpleContractArtifact, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, - ): Promise { - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - if (artifact.compilerOutput === undefined) { - throw new Error('Compiler output not found in the artifact file'); - } - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const bytecode = artifact.compilerOutput.evm.bytecode.object; - const abi = artifact.compilerOutput.abi; - const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; - if (Object.keys(logDecodeDependencies) !== undefined) { - for (const key of Object.keys(logDecodeDependencies)) { - logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; - } - } - return ERC20BridgeSamplerContract.deployAsync( - bytecode, - abi, - provider, - txDefaults, - logDecodeDependenciesAbiOnly, - ); - } - - public static async deployWithLibrariesFrom0xArtifactAsync( - artifact: ContractArtifact, - libraryArtifacts: { [libraryName: string]: ContractArtifact }, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, - ): Promise { - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - if (artifact.compilerOutput === undefined) { - throw new Error('Compiler output not found in the artifact file'); - } - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const abi = artifact.compilerOutput.abi; - const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; - if (Object.keys(logDecodeDependencies) !== undefined) { - for (const key of Object.keys(logDecodeDependencies)) { - logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; - } - } - const libraryAddresses = await ERC20BridgeSamplerContract._deployLibrariesAsync( - artifact, - libraryArtifacts, - new Web3Wrapper(provider), - txDefaults, - ); - const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses); - return ERC20BridgeSamplerContract.deployAsync( - bytecode, - abi, - provider, - txDefaults, - logDecodeDependenciesAbiOnly, - ); - } - - public static async deployAsync( - bytecode: string, - abi: ContractAbi, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractAbi }, - ): Promise { - assert.isHexString('bytecode', bytecode); - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const constructorAbi = BaseContract._lookupConstructorAbi(abi); - [] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString); - const iface = new ethers.utils.Interface(abi); - const deployInfo = iface.deployFunction; - const txData = deployInfo.encode(bytecode, []); - const web3Wrapper = new Web3Wrapper(provider); - const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( - { - data: txData, - ...txDefaults, - }, - web3Wrapper.estimateGasAsync.bind(web3Wrapper), - ); - const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); - logUtils.log(`transactionHash: ${txHash}`); - const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash); - logUtils.log(`ERC20BridgeSampler successfully deployed at ${txReceipt.contractAddress}`); - const contractInstance = new ERC20BridgeSamplerContract( - txReceipt.contractAddress as string, - provider, - txDefaults, - logDecodeDependencies, - ); - contractInstance.constructorArgs = []; - return contractInstance; - } - - /** - * @returns The contract ABI - */ - public static ABI(): ContractAbi { - const abi = [ - { - constant: true, - inputs: [ - { - name: 'callDatas', - type: 'bytes[]', - }, - ], - name: 'batchCall', - outputs: [ - { - name: 'callResults', - type: 'bytes[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - ], - name: 'getLiquidityProviderFromRegistry', - outputs: [ - { - name: 'providerAddress', - type: 'address', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'orders', - type: 'tuple[]', - components: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - { - name: 'makerFeeAssetData', - type: 'bytes', - }, - { - name: 'takerFeeAssetData', - type: 'bytes', - }, - ], - }, - { - name: 'orderSignatures', - type: 'bytes[]', - }, - { - name: 'devUtilsAddress', - type: 'address', - }, - ], - name: 'getOrderFillableMakerAssetAmounts', - outputs: [ - { - name: 'orderFillableMakerAssetAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'orders', - type: 'tuple[]', - components: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - { - name: 'makerFeeAssetData', - type: 'bytes', - }, - { - name: 'takerFeeAssetData', - type: 'bytes', - }, - ], - }, - { - name: 'orderSignatures', - type: 'bytes[]', - }, - { - name: 'devUtilsAddress', - type: 'address', - }, - ], - name: 'getOrderFillableTakerAssetAmounts', - outputs: [ - { - name: 'orderFillableTakerAssetAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'curveInfo', - type: 'tuple', - components: [ - { - name: 'poolAddress', - type: 'address', - }, - { - name: 'sellQuoteFunctionSelector', - type: 'bytes4', - }, - { - name: 'buyQuoteFunctionSelector', - type: 'bytes4', - }, - ], - }, - { - name: 'fromTokenIdx', - type: 'int128', - }, - { - name: 'toTokenIdx', - type: 'int128', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromCurve', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromEth2Dai', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromKyberNetwork', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromLiquidityProviderRegistry', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromUniswap', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'path', - type: 'address[]', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromUniswapV2', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'curveInfo', - type: 'tuple', - components: [ - { - name: 'poolAddress', - type: 'address', - }, - { - name: 'sellQuoteFunctionSelector', - type: 'bytes4', - }, - { - name: 'buyQuoteFunctionSelector', - type: 'bytes4', - }, - ], - }, - { - name: 'fromTokenIdx', - type: 'int128', - }, - { - name: 'toTokenIdx', - type: 'int128', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromCurve', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromEth2Dai', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'intermediateToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromEth2DaiHop', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromKyberNetwork', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromLiquidityProviderRegistry', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'multibridge', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'intermediateToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromMultiBridge', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromUniswap', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'path', - type: 'address[]', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromUniswapV2', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - ] as ContractAbi; - return abi; - } - - protected static async _deployLibrariesAsync( - artifact: ContractArtifact, - libraryArtifacts: { [libraryName: string]: ContractArtifact }, - web3Wrapper: Web3Wrapper, - txDefaults: Partial, - libraryAddresses: { [libraryName: string]: string } = {}, - ): Promise<{ [libraryName: string]: string }> { - const links = artifact.compilerOutput.evm.bytecode.linkReferences; - // Go through all linked libraries, recursively deploying them if necessary. - for (const link of Object.values(links)) { - for (const libraryName of Object.keys(link)) { - if (!libraryAddresses[libraryName]) { - // Library not yet deployed. - const libraryArtifact = libraryArtifacts[libraryName]; - if (!libraryArtifact) { - throw new Error(`Missing artifact for linked library "${libraryName}"`); - } - // Deploy any dependent libraries used by this library. - await ERC20BridgeSamplerContract._deployLibrariesAsync( - libraryArtifact, - libraryArtifacts, - web3Wrapper, - txDefaults, - libraryAddresses, - ); - // Deploy this library. - const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses); - const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( - { - data: linkedLibraryBytecode, - ...txDefaults, - }, - web3Wrapper.estimateGasAsync.bind(web3Wrapper), - ); - const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); - logUtils.log(`transactionHash: ${txHash}`); - const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash); - logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`); - libraryAddresses[libraryArtifact.contractName] = contractAddress as string; - } - } - } - return libraryAddresses; - } - - public getFunctionSignature(methodName: string): string { - const index = this._methodABIIndex[methodName]; - const methodAbi = ERC20BridgeSamplerContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion - const functionSignature = methodAbiToFunctionSignature(methodAbi); - return functionSignature; - } - - public getABIDecodedTransactionData(methodName: string, callData: string): T { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as ERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - } - - public getABIDecodedReturnData(methodName: string, callData: string): T { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as ERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); - return abiDecodedCallData; - } - - public getSelector(methodName: string): string { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as ERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - return abiEncoder.getSelector(); - } - - /** - * Call multiple public functions on this contract in a single transaction. - * @param callDatas ABI-encoded call data for each function call. - * @returns callResults ABI-encoded results data for each call. - */ - public batchCall(callDatas: string[]): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isArray('callDatas', callDatas); - const functionSignature = 'batchCall(bytes[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [callDatas]); - }, - }; - } - /** - * Returns the address of a liquidity provider for the given market - * (takerToken, makerToken), from a registry of liquidity providers. - * Returns address(0) if no such provider exists in the registry. - * @param takerToken Taker asset managed by liquidity provider. - * @param makerToken Maker asset managed by liquidity provider. - * @returns providerAddress Address of the liquidity provider. - */ - public getLiquidityProviderFromRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - const functionSignature = 'getLiquidityProviderFromRegistry(address,address,address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - ]); - }, - }; - } - /** - * Queries the fillable taker asset amounts of native orders. - * Effectively ignores orders that have empty signatures or - * @param orders Native orders to query. - * @param orderSignatures Signatures for each respective order in `orders`. - * @param devUtilsAddress Address to the DevUtils contract. - * @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in `orders`. - */ - public getOrderFillableMakerAssetAmounts( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - orderSignatures: string[], - devUtilsAddress: string, - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isArray('orders', orders); - assert.isArray('orderSignatures', orderSignatures); - assert.isString('devUtilsAddress', devUtilsAddress); - const functionSignature = - 'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - orders, - orderSignatures, - devUtilsAddress.toLowerCase(), - ]); - }, - }; - } - /** - * Queries the fillable taker asset amounts of native orders. - * Effectively ignores orders that have empty signatures or - * maker/taker asset amounts (returning 0). - * @param orders Native orders to query. - * @param orderSignatures Signatures for each respective order in `orders`. - * @param devUtilsAddress Address to the DevUtils contract. - * @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in `orders`. - */ - public getOrderFillableTakerAssetAmounts( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - orderSignatures: string[], - devUtilsAddress: string, - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isArray('orders', orders); - assert.isArray('orderSignatures', orderSignatures); - assert.isString('devUtilsAddress', devUtilsAddress); - const functionSignature = - 'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - orders, - orderSignatures, - devUtilsAddress.toLowerCase(), - ]); - }, - }; - } - /** - * Sample buy quotes from Curve. - * @param curveInfo Curve information specific to this token pair. - * @param fromTokenIdx Index of the taker token (what to sell). - * @param toTokenIdx Index of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromCurve( - curveInfo: { poolAddress: string; sellQuoteFunctionSelector: string; buyQuoteFunctionSelector: string }, - fromTokenIdx: BigNumber, - toTokenIdx: BigNumber, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - - assert.isBigNumber('fromTokenIdx', fromTokenIdx); - assert.isBigNumber('toTokenIdx', toTokenIdx); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromCurve((address,bytes4,bytes4),int128,int128,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - curveInfo, - fromTokenIdx, - toTokenIdx, - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from Eth2Dai/Oasis. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromEth2Dai( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromEth2Dai(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from Kyber. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromKyberNetwork( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromKyberNetwork(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from an arbitrary on-chain liquidity provider. - * @param registryAddress Address of the liquidity provider registry contract. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromLiquidityProviderRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromLiquidityProviderRegistry(address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from Uniswap. - * @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. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromUniswap( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromUniswap(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from UniswapV2. - * @param path Token route. Should be takerToken -> makerToken. - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromUniswapV2(path: string[], makerTokenAmounts: BigNumber[]): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isArray('path', path); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromUniswapV2(address[],uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [path, makerTokenAmounts]); - }, - }; - } - /** - * Sample sell quotes from Curve. - * @param curveInfo Curve information specific to this token pair. - * @param fromTokenIdx Index of the taker token (what to sell). - * @param toTokenIdx Index of the maker token (what to buy). - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromCurve( - curveInfo: { poolAddress: string; sellQuoteFunctionSelector: string; buyQuoteFunctionSelector: string }, - fromTokenIdx: BigNumber, - toTokenIdx: BigNumber, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - - assert.isBigNumber('fromTokenIdx', fromTokenIdx); - assert.isBigNumber('toTokenIdx', toTokenIdx); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromCurve((address,bytes4,bytes4),int128,int128,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - curveInfo, - fromTokenIdx, - toTokenIdx, - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Eth2Dai/Oasis. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromEth2Dai( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromEth2Dai(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Eth2Dai/Oasis using a hop to an intermediate token. - * I.e WBTC/DAI via ETH or WBTC/ETH via DAI - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param intermediateToken Address of the token to hop to. - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromEth2DaiHop( - takerToken: string, - makerToken: string, - intermediateToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isString('intermediateToken', intermediateToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromEth2DaiHop(address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - intermediateToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Kyber. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromKyberNetwork( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromKyberNetwork(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from an arbitrary on-chain liquidity provider. - * @param registryAddress Address of the liquidity provider registry contract. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromLiquidityProviderRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromLiquidityProviderRegistry(address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from MultiBridge. - * @param multibridge Address of the MultiBridge contract. - * @param takerToken Address of the taker token (what to sell). - * @param intermediateToken The address of the intermediate token to use - * in an indirect route. - * @param makerToken Address of the maker token (what to buy). - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromMultiBridge( - multibridge: string, - takerToken: string, - intermediateToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('multibridge', multibridge); - assert.isString('takerToken', takerToken); - assert.isString('intermediateToken', intermediateToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromMultiBridge(address,address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - multibridge.toLowerCase(), - takerToken.toLowerCase(), - intermediateToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Uniswap. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromUniswap( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromUniswap(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from UniswapV2. - * @param path Token route. Should be takerToken -> makerToken - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromUniswapV2(path: string[], takerTokenAmounts: BigNumber[]): ContractFunctionObj { - const self = (this as any) as ERC20BridgeSamplerContract; - assert.isArray('path', path); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromUniswapV2(address[],uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [path, takerTokenAmounts]); - }, - }; - } - - constructor( - address: string, - supportedProvider: SupportedProvider, - txDefaults?: Partial, - logDecodeDependencies?: { [contractName: string]: ContractAbi }, - deployedBytecode: string | undefined = ERC20BridgeSamplerContract.deployedBytecode, - ) { - super( - 'ERC20BridgeSampler', - ERC20BridgeSamplerContract.ABI(), - address, - supportedProvider, - txDefaults, - logDecodeDependencies, - deployedBytecode, - ); - classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); - ERC20BridgeSamplerContract.ABI().forEach((item, index) => { - if (item.type === 'function') { - const methodAbi = item as MethodAbi; - this._methodABIIndex[methodAbi.name] = index; - } - }); - } -} - -// tslint:disable:max-file-line-count -// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align -// tslint:enable:trailing-comma whitespace no-trailing-whitespace diff --git a/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts b/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts deleted file mode 100644 index ef0c2dc001..0000000000 --- a/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts +++ /dev/null @@ -1,1564 +0,0 @@ -// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming -// tslint:disable:whitespace no-unbound-method no-trailing-whitespace -// tslint:disable:no-unused-variable -import { - AwaitTransactionSuccessOpts, - ContractFunctionObj, - ContractTxFunctionObj, - SendTransactionOpts, - BaseContract, - PromiseWithTransactionHash, - methodAbiToFunctionSignature, - linkLibrariesInBytecode, -} from '@0x/base-contract'; -import { schemas } from '@0x/json-schemas'; -import { - BlockParam, - BlockParamLiteral, - BlockRange, - CallData, - ContractAbi, - ContractArtifact, - DecodedLogArgs, - MethodAbi, - TransactionReceiptWithDecodedLogs, - TxData, - TxDataPayable, - SupportedProvider, -} from 'ethereum-types'; -import { BigNumber, classUtils, hexUtils, logUtils, providerUtils } from '@0x/utils'; -import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types'; -import { Web3Wrapper } from '@0x/web3-wrapper'; -import { assert } from '@0x/assert'; -import * as ethers from 'ethers'; -// tslint:enable:no-unused-variable - -/* istanbul ignore next */ -// tslint:disable:array-type -// tslint:disable:no-parameter-reassignment -// tslint:disable-next-line:class-name -export class IERC20BridgeSamplerContract extends BaseContract { - /** - * @ignore - */ - public static deployedBytecode: string | undefined; - public static contractName = 'IERC20BridgeSampler'; - private readonly _methodABIIndex: { [name: string]: number } = {}; - public static async deployFrom0xArtifactAsync( - artifact: ContractArtifact | SimpleContractArtifact, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, - ): Promise { - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - if (artifact.compilerOutput === undefined) { - throw new Error('Compiler output not found in the artifact file'); - } - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const bytecode = artifact.compilerOutput.evm.bytecode.object; - const abi = artifact.compilerOutput.abi; - const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; - if (Object.keys(logDecodeDependencies) !== undefined) { - for (const key of Object.keys(logDecodeDependencies)) { - logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; - } - } - return IERC20BridgeSamplerContract.deployAsync( - bytecode, - abi, - provider, - txDefaults, - logDecodeDependenciesAbiOnly, - ); - } - - public static async deployWithLibrariesFrom0xArtifactAsync( - artifact: ContractArtifact, - libraryArtifacts: { [libraryName: string]: ContractArtifact }, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, - ): Promise { - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - if (artifact.compilerOutput === undefined) { - throw new Error('Compiler output not found in the artifact file'); - } - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const abi = artifact.compilerOutput.abi; - const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {}; - if (Object.keys(logDecodeDependencies) !== undefined) { - for (const key of Object.keys(logDecodeDependencies)) { - logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi; - } - } - const libraryAddresses = await IERC20BridgeSamplerContract._deployLibrariesAsync( - artifact, - libraryArtifacts, - new Web3Wrapper(provider), - txDefaults, - ); - const bytecode = linkLibrariesInBytecode(artifact, libraryAddresses); - return IERC20BridgeSamplerContract.deployAsync( - bytecode, - abi, - provider, - txDefaults, - logDecodeDependenciesAbiOnly, - ); - } - - public static async deployAsync( - bytecode: string, - abi: ContractAbi, - supportedProvider: SupportedProvider, - txDefaults: Partial, - logDecodeDependencies: { [contractName: string]: ContractAbi }, - ): Promise { - assert.isHexString('bytecode', bytecode); - assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ - schemas.addressSchema, - schemas.numberSchema, - schemas.jsNumber, - ]); - const provider = providerUtils.standardizeOrThrow(supportedProvider); - const constructorAbi = BaseContract._lookupConstructorAbi(abi); - [] = BaseContract._formatABIDataItemList(constructorAbi.inputs, [], BaseContract._bigNumberToString); - const iface = new ethers.utils.Interface(abi); - const deployInfo = iface.deployFunction; - const txData = deployInfo.encode(bytecode, []); - const web3Wrapper = new Web3Wrapper(provider); - const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( - { - data: txData, - ...txDefaults, - }, - web3Wrapper.estimateGasAsync.bind(web3Wrapper), - ); - const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); - logUtils.log(`transactionHash: ${txHash}`); - const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash); - logUtils.log(`IERC20BridgeSampler successfully deployed at ${txReceipt.contractAddress}`); - const contractInstance = new IERC20BridgeSamplerContract( - txReceipt.contractAddress as string, - provider, - txDefaults, - logDecodeDependencies, - ); - contractInstance.constructorArgs = []; - return contractInstance; - } - - /** - * @returns The contract ABI - */ - public static ABI(): ContractAbi { - const abi = [ - { - constant: true, - inputs: [ - { - name: 'callDatas', - type: 'bytes[]', - }, - ], - name: 'batchCall', - outputs: [ - { - name: 'callResults', - type: 'bytes[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - ], - name: 'getLiquidityProviderFromRegistry', - outputs: [ - { - name: 'providerAddress', - type: 'address', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'orders', - type: 'tuple[]', - components: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - { - name: 'makerFeeAssetData', - type: 'bytes', - }, - { - name: 'takerFeeAssetData', - type: 'bytes', - }, - ], - }, - { - name: 'orderSignatures', - type: 'bytes[]', - }, - { - name: 'devUtilsAddress', - type: 'address', - }, - ], - name: 'getOrderFillableMakerAssetAmounts', - outputs: [ - { - name: 'orderFillableMakerAssetAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'orders', - type: 'tuple[]', - components: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'takerAddress', - type: 'address', - }, - { - name: 'feeRecipientAddress', - type: 'address', - }, - { - name: 'senderAddress', - type: 'address', - }, - { - name: 'makerAssetAmount', - type: 'uint256', - }, - { - name: 'takerAssetAmount', - type: 'uint256', - }, - { - name: 'makerFee', - type: 'uint256', - }, - { - name: 'takerFee', - type: 'uint256', - }, - { - name: 'expirationTimeSeconds', - type: 'uint256', - }, - { - name: 'salt', - type: 'uint256', - }, - { - name: 'makerAssetData', - type: 'bytes', - }, - { - name: 'takerAssetData', - type: 'bytes', - }, - { - name: 'makerFeeAssetData', - type: 'bytes', - }, - { - name: 'takerFeeAssetData', - type: 'bytes', - }, - ], - }, - { - name: 'orderSignatures', - type: 'bytes[]', - }, - { - name: 'devUtilsAddress', - type: 'address', - }, - ], - name: 'getOrderFillableTakerAssetAmounts', - outputs: [ - { - name: 'orderFillableTakerAssetAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'curveAddress', - type: 'address', - }, - { - name: 'fromTokenIdx', - type: 'int128', - }, - { - name: 'toTokenIdx', - type: 'int128', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromCurve', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromEth2Dai', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - { - name: 'opts', - type: 'tuple', - components: [ - { - name: 'targetSlippageBps', - type: 'uint256', - }, - { - name: 'maxIterations', - type: 'uint256', - }, - ], - }, - ], - name: 'sampleBuysFromKyberNetwork', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - { - name: 'opts', - type: 'tuple', - components: [ - { - name: 'targetSlippageBps', - type: 'uint256', - }, - { - name: 'maxIterations', - type: 'uint256', - }, - ], - }, - ], - name: 'sampleBuysFromLiquidityProviderRegistry', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromUniswap', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'path', - type: 'address[]', - }, - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleBuysFromUniswapV2', - outputs: [ - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'curveAddress', - type: 'address', - }, - { - name: 'fromTokenIdx', - type: 'int128', - }, - { - name: 'toTokenIdx', - type: 'int128', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromCurve', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromEth2Dai', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromKyberNetwork', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'registryAddress', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromLiquidityProviderRegistry', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'multibridge', - type: 'address', - }, - { - name: 'takerToken', - type: 'address', - }, - { - name: 'intermediateToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromMultiBridge', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'takerToken', - type: 'address', - }, - { - name: 'makerToken', - type: 'address', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromUniswap', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'path', - type: 'address[]', - }, - { - name: 'takerTokenAmounts', - type: 'uint256[]', - }, - ], - name: 'sampleSellsFromUniswapV2', - outputs: [ - { - name: 'makerTokenAmounts', - type: 'uint256[]', - }, - ], - payable: false, - stateMutability: 'view', - type: 'function', - }, - ] as ContractAbi; - return abi; - } - - protected static async _deployLibrariesAsync( - artifact: ContractArtifact, - libraryArtifacts: { [libraryName: string]: ContractArtifact }, - web3Wrapper: Web3Wrapper, - txDefaults: Partial, - libraryAddresses: { [libraryName: string]: string } = {}, - ): Promise<{ [libraryName: string]: string }> { - const links = artifact.compilerOutput.evm.bytecode.linkReferences; - // Go through all linked libraries, recursively deploying them if necessary. - for (const link of Object.values(links)) { - for (const libraryName of Object.keys(link)) { - if (!libraryAddresses[libraryName]) { - // Library not yet deployed. - const libraryArtifact = libraryArtifacts[libraryName]; - if (!libraryArtifact) { - throw new Error(`Missing artifact for linked library "${libraryName}"`); - } - // Deploy any dependent libraries used by this library. - await IERC20BridgeSamplerContract._deployLibrariesAsync( - libraryArtifact, - libraryArtifacts, - web3Wrapper, - txDefaults, - libraryAddresses, - ); - // Deploy this library. - const linkedLibraryBytecode = linkLibrariesInBytecode(libraryArtifact, libraryAddresses); - const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( - { - data: linkedLibraryBytecode, - ...txDefaults, - }, - web3Wrapper.estimateGasAsync.bind(web3Wrapper), - ); - const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults); - logUtils.log(`transactionHash: ${txHash}`); - const { contractAddress } = await web3Wrapper.awaitTransactionSuccessAsync(txHash); - logUtils.log(`${libraryArtifact.contractName} successfully deployed at ${contractAddress}`); - libraryAddresses[libraryArtifact.contractName] = contractAddress as string; - } - } - } - return libraryAddresses; - } - - public getFunctionSignature(methodName: string): string { - const index = this._methodABIIndex[methodName]; - const methodAbi = IERC20BridgeSamplerContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion - const functionSignature = methodAbiToFunctionSignature(methodAbi); - return functionSignature; - } - - public getABIDecodedTransactionData(methodName: string, callData: string): T { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as IERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - const abiDecodedCallData = abiEncoder.strictDecode(callData); - return abiDecodedCallData; - } - - public getABIDecodedReturnData(methodName: string, callData: string): T { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as IERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); - return abiDecodedCallData; - } - - public getSelector(methodName: string): string { - const functionSignature = this.getFunctionSignature(methodName); - const self = (this as any) as IERC20BridgeSamplerContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - return abiEncoder.getSelector(); - } - - /** - * Call multiple public functions on this contract in a single transaction. - * @param callDatas ABI-encoded call data for each function call. - * @returns callResults ABI-encoded results data for each call. - */ - public batchCall(callDatas: string[]): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isArray('callDatas', callDatas); - const functionSignature = 'batchCall(bytes[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [callDatas]); - }, - }; - } - /** - * Returns the address of a liquidity provider for the given market - * (takerToken, makerToken), from a registry of liquidity providers. - * Returns address(0) if no such provider exists in the registry. - * @param takerToken Taker asset managed by liquidity provider. - * @param makerToken Maker asset managed by liquidity provider. - * @returns providerAddress Address of the liquidity provider. - */ - public getLiquidityProviderFromRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - const functionSignature = 'getLiquidityProviderFromRegistry(address,address,address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - ]); - }, - }; - } - /** - * Queries the fillable maker asset amounts of native orders. - * @param orders Native orders to query. - * @param orderSignatures Signatures for each respective order in `orders`. - * @param devUtilsAddress Address to the DevUtils contract. - * @returns orderFillableMakerAssetAmounts How much maker asset can be filled by each order in `orders`. - */ - public getOrderFillableMakerAssetAmounts( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - orderSignatures: string[], - devUtilsAddress: string, - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isArray('orders', orders); - assert.isArray('orderSignatures', orderSignatures); - assert.isString('devUtilsAddress', devUtilsAddress); - const functionSignature = - 'getOrderFillableMakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - orders, - orderSignatures, - devUtilsAddress.toLowerCase(), - ]); - }, - }; - } - /** - * Queries the fillable taker asset amounts of native orders. - * @param orders Native orders to query. - * @param orderSignatures Signatures for each respective order in `orders`. - * @param devUtilsAddress Address to the DevUtils contract. - * @returns orderFillableTakerAssetAmounts How much taker asset can be filled by each order in `orders`. - */ - public getOrderFillableTakerAssetAmounts( - orders: Array<{ - makerAddress: string; - takerAddress: string; - feeRecipientAddress: string; - senderAddress: string; - makerAssetAmount: BigNumber; - takerAssetAmount: BigNumber; - makerFee: BigNumber; - takerFee: BigNumber; - expirationTimeSeconds: BigNumber; - salt: BigNumber; - makerAssetData: string; - takerAssetData: string; - makerFeeAssetData: string; - takerFeeAssetData: string; - }>, - orderSignatures: string[], - devUtilsAddress: string, - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isArray('orders', orders); - assert.isArray('orderSignatures', orderSignatures); - assert.isString('devUtilsAddress', devUtilsAddress); - const functionSignature = - 'getOrderFillableTakerAssetAmounts((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[],bytes[],address)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - orders, - orderSignatures, - devUtilsAddress.toLowerCase(), - ]); - }, - }; - } - /** - * Sample buy quotes from Curve. - * @param curveAddress Address of the Curve contract. - * @param fromTokenIdx Index of the taker token (what to sell). - * @param toTokenIdx Index of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromCurve( - curveAddress: string, - fromTokenIdx: BigNumber, - toTokenIdx: BigNumber, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('curveAddress', curveAddress); - assert.isBigNumber('fromTokenIdx', fromTokenIdx); - assert.isBigNumber('toTokenIdx', toTokenIdx); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromCurve(address,int128,int128,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - curveAddress.toLowerCase(), - fromTokenIdx, - toTokenIdx, - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from Eth2Dai/Oasis. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromEth2Dai( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromEth2Dai(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from Kyber. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @param opts `FakeBuyOptions` specifying target slippage and max iterations. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromKyberNetwork( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - opts: { targetSlippageBps: BigNumber; maxIterations: BigNumber }, - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - - const functionSignature = 'sampleBuysFromKyberNetwork(address,address,uint256[],(uint256,uint256))'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - opts, - ]); - }, - }; - } - /** - * Sample buy quotes from an arbitrary on-chain liquidity provider. - * @param registryAddress Address of the liquidity provider registry contract. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @param opts `FakeBuyOptions` specifying target slippage and max iterations. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromLiquidityProviderRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - opts: { targetSlippageBps: BigNumber; maxIterations: BigNumber }, - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - - const functionSignature = - 'sampleBuysFromLiquidityProviderRegistry(address,address,address,uint256[],(uint256,uint256))'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - opts, - ]); - }, - }; - } - /** - * Sample buy quotes from Uniswap. - * @param takerToken Address of the taker token (what to sell). - * @param makerToken Address of the maker token (what to buy). - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromUniswap( - takerToken: string, - makerToken: string, - makerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromUniswap(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - makerTokenAmounts, - ]); - }, - }; - } - /** - * Sample buy quotes from UniswapV2. - * @param path Token route. - * @param makerTokenAmounts Maker token buy amount for each sample. - * @returns takerTokenAmounts Taker amounts sold at each maker token amount. - */ - public sampleBuysFromUniswapV2(path: string[], makerTokenAmounts: BigNumber[]): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isArray('path', path); - assert.isArray('makerTokenAmounts', makerTokenAmounts); - const functionSignature = 'sampleBuysFromUniswapV2(address[],uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [path, makerTokenAmounts]); - }, - }; - } - /** - * Sample sell quotes from Curve. - * @param curveAddress Address of the Curve contract. - * @param fromTokenIdx Index of the taker token (what to sell). - * @param toTokenIdx Index of the maker token (what to buy). - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromCurve( - curveAddress: string, - fromTokenIdx: BigNumber, - toTokenIdx: BigNumber, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('curveAddress', curveAddress); - assert.isBigNumber('fromTokenIdx', fromTokenIdx); - assert.isBigNumber('toTokenIdx', toTokenIdx); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromCurve(address,int128,int128,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - curveAddress.toLowerCase(), - fromTokenIdx, - toTokenIdx, - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Eth2Dai/Oasis. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromEth2Dai( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromEth2Dai(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Kyber. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromKyberNetwork( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromKyberNetwork(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from an arbitrary on-chain liquidity provider. - * @param registryAddress Address of the liquidity provider registry contract. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromLiquidityProviderRegistry( - registryAddress: string, - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('registryAddress', registryAddress); - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromLiquidityProviderRegistry(address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - registryAddress.toLowerCase(), - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from MultiBridge. - * @param multibridge Address of the MultiBridge contract. - * @param takerToken Address of the taker token (what to sell). - * @param intermediateToken The address of the intermediate token to use - * in an indirect route. - * @param makerToken Address of the maker token (what to buy). - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromMultiBridge( - multibridge: string, - takerToken: string, - intermediateToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('multibridge', multibridge); - assert.isString('takerToken', takerToken); - assert.isString('intermediateToken', intermediateToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromMultiBridge(address,address,address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - multibridge.toLowerCase(), - takerToken.toLowerCase(), - intermediateToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from Uniswap. - * @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. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromUniswap( - takerToken: string, - makerToken: string, - takerTokenAmounts: BigNumber[], - ): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isString('takerToken', takerToken); - assert.isString('makerToken', makerToken); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromUniswap(address,address,uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [ - takerToken.toLowerCase(), - makerToken.toLowerCase(), - takerTokenAmounts, - ]); - }, - }; - } - /** - * Sample sell quotes from UniswapV2. - * @param path Token route. - * @param takerTokenAmounts Taker token sell amount for each sample. - * @returns makerTokenAmounts Maker amounts bought at each taker token amount. - */ - public sampleSellsFromUniswapV2(path: string[], takerTokenAmounts: BigNumber[]): ContractFunctionObj { - const self = (this as any) as IERC20BridgeSamplerContract; - assert.isArray('path', path); - assert.isArray('takerTokenAmounts', takerTokenAmounts); - const functionSignature = 'sampleSellsFromUniswapV2(address[],uint256[])'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { data: this.getABIEncodedTransactionData(), ...callData }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [path, takerTokenAmounts]); - }, - }; - } - - constructor( - address: string, - supportedProvider: SupportedProvider, - txDefaults?: Partial, - logDecodeDependencies?: { [contractName: string]: ContractAbi }, - deployedBytecode: string | undefined = IERC20BridgeSamplerContract.deployedBytecode, - ) { - super( - 'IERC20BridgeSampler', - IERC20BridgeSamplerContract.ABI(), - address, - supportedProvider, - txDefaults, - logDecodeDependencies, - deployedBytecode, - ); - classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); - IERC20BridgeSamplerContract.ABI().forEach((item, index) => { - if (item.type === 'function') { - const methodAbi = item as MethodAbi; - this._methodABIIndex[methodAbi.name] = index; - } - }); - } -} - -// tslint:disable:max-file-line-count -// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align -// tslint:enable:trailing-comma whitespace no-trailing-whitespace diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index 363416beb6..f4025e4d01 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -1,38 +1,109 @@ -export { ERC20BridgeSamplerContract } from './generated-wrappers/erc20_bridge_sampler'; - -export { ContractAddresses } from '@0x/contract-addresses'; - -export { ContractWrappers } from './contract_wrappers'; -export { DevUtilsContract } from './generated-wrappers/dev_utils'; -export { IERC20BridgeSamplerContract } from './generated-wrappers/i_erc20_bridge_sampler'; -export { IAssetDataContract } from './generated-wrappers/i_asset_data'; // used for synchronously encoding and decoding asset data export { + AwaitTransactionSuccessOpts, + ContractEvent, + ContractFunctionObj, + ContractTxFunctionObj, + SendTransactionOpts, + SubscriptionErrors, +} from '@0x/base-contract'; +export { ContractAddresses } from '@0x/contract-addresses'; +export { + DecodedLogEvent, + EventCallback, + IndexedFilterValues, + SimpleContractArtifact, + SimpleEvmBytecodeOutput, + SimpleEvmOutput, + SimpleStandardContractOutput, +} from '@0x/types'; +export { AbiDecoder, DecodedCalldata } from '@0x/utils'; +export { + AbiDefinition, + BlockParam, + BlockParamLiteral, + BlockRange, + CallData, + CompilerOpts, + CompilerSettings, + CompilerSettingsMetadata, + ConstructorAbi, + ConstructorStateMutability, + ContractAbi, + ContractArtifact, + ContractChainData, + ContractChains, + ContractEventArg, + DataItem, + DecodedLogArgs, + DecodedLogEntry, + DecodedLogEntryEvent, + DevdocOutput, + EIP1193Event, + EIP1193Provider, + EventAbi, + EventParameter, + EvmBytecodeOutput, + EvmBytecodeOutputLinkReferences, + EvmOutput, + FallbackAbi, + FunctionAbi, + GanacheProvider, + GethCallOverrides, + JSONRPCErrorCallback, + JSONRPCRequestPayload, + JSONRPCResponseError, + JSONRPCResponsePayload, + LogEntry, + LogEntryEvent, + LogWithDecodedArgs, + MethodAbi, + OptimizerSettings, + OutputField, + ParamDescription, + RawLog, + RevertErrorAbi, + StandardContractOutput, + StateMutability, + SupportedProvider, + TupleDataItem, + TxData, + TxDataPayable, + Web3JsProvider, + Web3JsV1Provider, + Web3JsV2Provider, + Web3JsV3Provider, + ZeroExProvider, +} from 'ethereum-types'; +export { ContractWrappers } from './contract_wrappers'; +export { CoordinatorContract } from './generated-wrappers/coordinator'; +export { DevUtilsContract } from './generated-wrappers/dev_utils'; +export { + ERC20TokenApprovalEventArgs, + ERC20TokenContract, ERC20TokenEventArgs, ERC20TokenEvents, ERC20TokenTransferEventArgs, - ERC20TokenApprovalEventArgs, - ERC20TokenContract, } from './generated-wrappers/erc20_token'; export { - ERC721TokenEventArgs, - ERC721TokenEvents, - ERC721TokenTransferEventArgs, ERC721TokenApprovalEventArgs, ERC721TokenApprovalForAllEventArgs, ERC721TokenContract, + ERC721TokenEventArgs, + ERC721TokenEvents, + ERC721TokenTransferEventArgs, } from './generated-wrappers/erc721_token'; export { - ExchangeEventArgs, - ExchangeEvents, - ExchangeSignatureValidatorApprovalEventArgs, - ExchangeFillEventArgs, + ExchangeAssetProxyRegisteredEventArgs, ExchangeCancelEventArgs, ExchangeCancelUpToEventArgs, - ExchangeAssetProxyRegisteredEventArgs, ExchangeContract, + ExchangeEventArgs, + ExchangeEvents, + ExchangeFillEventArgs, ExchangeOwnershipTransferredEventArgs, ExchangeProtocolFeeCollectorAddressEventArgs, ExchangeProtocolFeeMultiplierEventArgs, + ExchangeSignatureValidatorApprovalEventArgs, ExchangeTransactionExecutionEventArgs, } from './generated-wrappers/exchange'; export { @@ -41,17 +112,27 @@ export { ForwarderEvents, ForwarderOwnershipTransferredEventArgs, } from './generated-wrappers/forwarder'; +export { IAssetDataContract } from './generated-wrappers/i_asset_data'; // used for synchronously encoding and decoding asset data export { - WETH9EventArgs, - WETH9Events, - WETH9ApprovalEventArgs, - WETH9TransferEventArgs, - WETH9DepositEventArgs, - WETH9WithdrawalEventArgs, - WETH9Contract, -} from './generated-wrappers/weth9'; -export { CoordinatorContract } from './generated-wrappers/coordinator'; -export { OrderStatus, ContractError, ForwarderError, ContractWrappersConfig, OrderInfo } from './types'; + ITransformERC20Contract, + ITransformERC20EventArgs, + ITransformERC20Events, + ITransformERC20QuoteSignerUpdatedEventArgs, + ITransformERC20TransformedERC20EventArgs, + ITransformERC20TransformerDeployerUpdatedEventArgs, +} from './generated-wrappers/i_transform_erc20'; +export { + IZeroExContract, + IZeroExEventArgs, + IZeroExEvents, + IZeroExMetaTransactionExecutedEventArgs, + IZeroExMigratedEventArgs, + IZeroExOwnershipTransferredEventArgs, + IZeroExProxyFunctionUpdatedEventArgs, + IZeroExQuoteSignerUpdatedEventArgs, + IZeroExTransformedERC20EventArgs, + IZeroExTransformerDeployerUpdatedEventArgs, +} from './generated-wrappers/i_zero_ex'; export { StakingAuthorizedAddressAddedEventArgs, StakingAuthorizedAddressRemovedEventArgs, @@ -84,99 +165,12 @@ export { StakingProxyStakingContractDetachedFromProxyEventArgs, } from './generated-wrappers/staking_proxy'; export { - ITransformERC20Contract, - ITransformERC20EventArgs, - ITransformERC20Events, - ITransformERC20QuoteSignerUpdatedEventArgs, - ITransformERC20TransformerDeployerUpdatedEventArgs, - ITransformERC20TransformedERC20EventArgs, -} from './generated-wrappers/i_transform_erc20'; -export { - IZeroExContract, - IZeroExEventArgs, - IZeroExEvents, - IZeroExMetaTransactionExecutedEventArgs, - IZeroExMigratedEventArgs, - IZeroExOwnershipTransferredEventArgs, - IZeroExProxyFunctionUpdatedEventArgs, - IZeroExQuoteSignerUpdatedEventArgs, - IZeroExTransformedERC20EventArgs, - IZeroExTransformerDeployerUpdatedEventArgs, -} from './generated-wrappers/i_zero_ex'; -export { - BlockRange, - SupportedProvider, - TxData, - ContractAbi, - ContractArtifact, - DataItem, - CallData, - GethCallOverrides, - BlockParam, - ContractEventArg, - DecodedLogArgs, - LogWithDecodedArgs, - CompilerOpts, - StandardContractOutput, - ContractChains, - EventParameter, - TupleDataItem, - TxDataPayable, - BlockParamLiteral, - AbiDefinition, - Web3JsProvider, - GanacheProvider, - EIP1193Provider, - ZeroExProvider, - LogEntry, - RawLog, - CompilerSettings, - ContractChainData, - EIP1193Event, - JSONRPCRequestPayload, - JSONRPCErrorCallback, - DecodedLogEntry, - LogEntryEvent, - DevdocOutput, - EvmOutput, - FunctionAbi, - EventAbi, - Web3JsV1Provider, - Web3JsV2Provider, - Web3JsV3Provider, - CompilerSettingsMetadata, - OptimizerSettings, - OutputField, - DecodedLogEntryEvent, - ParamDescription, - EvmBytecodeOutput, - EvmBytecodeOutputLinkReferences, - JSONRPCResponsePayload, - MethodAbi, - ConstructorAbi, - FallbackAbi, - ConstructorStateMutability, - JSONRPCResponseError, - StateMutability, - RevertErrorAbi, -} from 'ethereum-types'; - -export { - SimpleContractArtifact, - SimpleStandardContractOutput, - SimpleEvmOutput, - SimpleEvmBytecodeOutput, - EventCallback, - DecodedLogEvent, - IndexedFilterValues, -} from '@0x/types'; - -export { AbiDecoder, DecodedCalldata } from '@0x/utils'; -export { - ContractEvent, - SendTransactionOpts, - AwaitTransactionSuccessOpts, - ContractFunctionObj, - ContractTxFunctionObj, - SubscriptionErrors, -} from '@0x/base-contract'; + WETH9ApprovalEventArgs, + WETH9Contract, + WETH9DepositEventArgs, + WETH9EventArgs, + WETH9Events, + WETH9TransferEventArgs, + WETH9WithdrawalEventArgs, +} from './generated-wrappers/weth9'; +export { ContractError, ContractWrappersConfig, ForwarderError, OrderInfo, OrderStatus } from './types'; diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 63a4b77b81..b6be5535b6 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -69,13 +69,11 @@ "dependencies": { "@0x/base-contract": "^6.2.3", "@0x/contract-addresses": "^4.11.0", - "@0x/contract-wrappers": "^13.8.0", "@0x/contracts-asset-proxy": "^3.4.0", "@0x/contracts-coordinator": "^3.1.7", "@0x/contracts-dev-utils": "^1.3.5", "@0x/contracts-erc1155": "^2.1.7", "@0x/contracts-erc20": "^3.2.1", - "@0x/contracts-erc20-bridge-sampler": "^1.7.0", "@0x/contracts-erc721": "^3.1.7", "@0x/contracts-exchange": "^3.2.7", "@0x/contracts-exchange-forwarder": "^4.2.7", diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 67af1f6f78..9ffb30af57 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -14,9 +14,8 @@ import { CoordinatorRegistryContract, } from '@0x/contracts-coordinator'; import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils'; -import { artifacts as erc1155Artifacts } from '@0x/contracts-erc1155'; +import { artifacts as erc1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155'; import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; -import { artifacts as erc20BridgeSamplerArtifacts } from '@0x/contracts-erc20-bridge-sampler'; import { artifacts as erc721Artifacts, DummyERC721TokenContract } from '@0x/contracts-erc721'; import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange'; import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder'; @@ -29,15 +28,15 @@ import { import { AffiliateFeeTransformerContract, artifacts as exchangeProxyArtifacts, + BridgeAdapterContract, FillQuoteTransformerContract, fullMigrateAsync as fullMigrateExchangeProxyAsync, ITokenSpenderContract, ITransformERC20Contract, PayTakerTransformerContract, WethTransformerContract, - ZeroExContract, } from '@0x/contracts-zero-ex'; -import { Web3ProviderEngine, ZeroExProvider } from '@0x/subproviders'; +import { Web3ProviderEngine } from '@0x/subproviders'; import { BigNumber, providerUtils } from '@0x/utils'; import { SupportedProvider, TxData } from 'ethereum-types'; @@ -54,58 +53,11 @@ const allArtifacts = { ...exchangeArtifacts, ...forwarderArtifacts, ...stakingArtifacts, - ...erc20BridgeSamplerArtifacts, ...exchangeProxyArtifacts, + ...assetProxyArtifacts, }; const { NULL_ADDRESS } = constants; -const NULL_ADDRESSES = { - erc20Proxy: NULL_ADDRESS, - erc721Proxy: NULL_ADDRESS, - erc1155Proxy: NULL_ADDRESS, - zrxToken: NULL_ADDRESS, - etherToken: NULL_ADDRESS, - exchange: NULL_ADDRESS, - assetProxyOwner: NULL_ADDRESS, - erc20BridgeProxy: NULL_ADDRESS, - zeroExGovernor: NULL_ADDRESS, - forwarder: NULL_ADDRESS, - coordinatorRegistry: NULL_ADDRESS, - coordinator: NULL_ADDRESS, - multiAssetProxy: NULL_ADDRESS, - staticCallProxy: NULL_ADDRESS, - devUtils: NULL_ADDRESS, - exchangeV2: NULL_ADDRESS, - zrxVault: NULL_ADDRESS, - staking: NULL_ADDRESS, - stakingProxy: NULL_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, - exchangeProxyGovernor: NULL_ADDRESS, - exchangeProxy: NULL_ADDRESS, - exchangeProxyAllowanceTarget: NULL_ADDRESS, - exchangeProxyTransformerDeployer: NULL_ADDRESS, - exchangeProxyFlashWallet: NULL_ADDRESS, - transformers: { - wethTransformer: NULL_ADDRESS, - payTakerTransformer: NULL_ADDRESS, - fillQuoteTransformer: NULL_ADDRESS, - affiliateFeeTransformer: NULL_ADDRESS, - }, -}; /** * Creates and deploys all the contracts that are required for the latest @@ -120,8 +72,22 @@ export async function runMigrationsAsync( ): Promise { const provider = providerUtils.standardizeOrThrow(supportedProvider); const chainId = new BigNumber(await providerUtils.getChainIdAsync(provider)); - const { exchangeV2 } = getContractAddressesForChainOrThrow(chainId.toNumber()); + // Proxies + const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC20Proxy, + provider, + txDefaults, + allArtifacts, + ); + const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC721Proxy, + provider, + txDefaults, + allArtifacts, + ); + + // ZRX const zrxToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync( erc20Artifacts.DummyERC20Token, provider, @@ -141,8 +107,6 @@ export async function runMigrationsAsync( allArtifacts, ); - await _migrateDummyTokensAsync(provider, txDefaults); - // Exchange const exchange = await ExchangeContract.deployFrom0xArtifactAsync( exchangeArtifacts.Exchange, @@ -152,135 +116,31 @@ export async function runMigrationsAsync( chainId, ); - // CoordinatorRegistry - const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( - coordinatorArtifacts.CoordinatorRegistry, - provider, - txDefaults, - allArtifacts, - ); - - // Coordinator - const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync( - coordinatorArtifacts.Coordinator, - provider, - txDefaults, - allArtifacts, - exchange.address, - chainId, - ); - - const [ - erc20Proxy, - erc721Proxy, - erc1155Proxy, - staticCallProxy, - multiAssetProxy, - erc20BridgeProxy, - ] = await _migrateAssetProxiesAsync(exchange, provider, txDefaults); - - // Dev Utils - const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( - devUtilsArtifacts.DevUtils, - devUtilsArtifacts, - provider, - txDefaults, - allArtifacts, - exchange.address, - NULL_ADDRESS, - NULL_ADDRESS, - ); - - const [zrxVault, stakingLogic, stakingProxy] = await _migrateStakingAsync( - exchange, - erc20Proxy, - zrxToken.address, - etherToken.address, - provider, - txDefaults, - ); - - // Forwarder - // Deployed after Exchange and Staking is configured as it queries - // in the constructor - const forwarder = await ForwarderContract.deployFrom0xArtifactAsync( - forwarderArtifacts.Forwarder, - provider, - txDefaults, - allArtifacts, - exchange.address, - exchangeV2, - etherToken.address, - ); - - const [ - exchangeProxy, - fillQuoteTransformer, - payTakerTransformer, - wethTransformer, - affiliateFeeTransformer, - exchangeProxyFlashWalletAddress, - exchangeProxyAllowanceTargetAddress, - ] = await _migrateExchangeProxyAsync(exchange, etherToken.address, provider, txDefaults); - - const contractAddresses = { - ...NULL_ADDRESSES, - erc20Proxy: erc20Proxy.address, - erc721Proxy: erc721Proxy.address, - erc1155Proxy: erc1155Proxy.address, - zrxToken: zrxToken.address, - etherToken: etherToken.address, - exchange: exchange.address, - erc20BridgeProxy: erc20BridgeProxy.address, - forwarder: forwarder.address, - coordinatorRegistry: coordinatorRegistry.address, - coordinator: coordinator.address, - multiAssetProxy: multiAssetProxy.address, - staticCallProxy: staticCallProxy.address, - devUtils: devUtils.address, - zrxVault: zrxVault.address, - staking: stakingLogic.address, - stakingProxy: stakingProxy.address, - exchangeProxy: exchangeProxy.address, - exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress, - exchangeProxyTransformerDeployer: txDefaults.from, - exchangeProxyFlashWallet: exchangeProxyFlashWalletAddress, - transformers: { - wethTransformer: wethTransformer.address, - payTakerTransformer: payTakerTransformer.address, - fillQuoteTransformer: fillQuoteTransformer.address, - affiliateFeeTransformer: affiliateFeeTransformer.address, - }, - }; - return contractAddresses; -} - -async function _migrateAssetProxiesAsync( - exchange: ExchangeContract, - provider: ZeroExProvider, - txDefaults: TxData, -): Promise< - [ - ERC20ProxyContract, - ERC721ProxyContract, - ERC1155ProxyContract, - StaticCallProxyContract, - MultiAssetProxyContract, - ERC20BridgeProxyContract - ] -> { - // Proxies - const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( - assetProxyArtifacts.ERC20Proxy, - provider, - txDefaults, - allArtifacts, - ); - const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync( - assetProxyArtifacts.ERC721Proxy, + // Dummy ERC20 tokens + for (const token of erc20TokenInfo) { + const totalSupply = new BigNumber(1000000000000000000000000000); + // tslint:disable-next-line:no-unused-variable + const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + erc20Artifacts.DummyERC20Token, + provider, + txDefaults, + allArtifacts, + token.name, + token.symbol, + token.decimals, + totalSupply, + ); + } + + // ERC721 + // tslint:disable-next-line:no-unused-variable + const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync( + erc721Artifacts.DummyERC721Token, provider, txDefaults, allArtifacts, + erc721TokenInfo[0].name, + erc721TokenInfo[0].symbol, ); // 1155 Asset Proxy @@ -305,29 +165,19 @@ async function _migrateAssetProxiesAsync( allArtifacts, ); - const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync( - assetProxyArtifacts.ERC20BridgeProxy, - provider, - txDefaults, - allArtifacts, - ); - await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); await erc721Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); await erc1155Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); await multiAssetProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); - await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); // MultiAssetProxy await erc20Proxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); await erc721Proxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); await erc1155Proxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); - await erc20BridgeProxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); await multiAssetProxy.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync(txDefaults); await multiAssetProxy.registerAssetProxy(erc721Proxy.address).awaitTransactionSuccessAsync(txDefaults); await multiAssetProxy.registerAssetProxy(erc1155Proxy.address).awaitTransactionSuccessAsync(txDefaults); await multiAssetProxy.registerAssetProxy(staticCallProxy.address).awaitTransactionSuccessAsync(txDefaults); - await multiAssetProxy.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults); // Register the Asset Proxies to the Exchange await exchange.registerAssetProxy(erc20Proxy.address).awaitTransactionSuccessAsync(txDefaults); @@ -335,26 +185,64 @@ async function _migrateAssetProxiesAsync( await exchange.registerAssetProxy(erc1155Proxy.address).awaitTransactionSuccessAsync(txDefaults); await exchange.registerAssetProxy(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); await exchange.registerAssetProxy(staticCallProxy.address).awaitTransactionSuccessAsync(txDefaults); + + // CoordinatorRegistry + const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( + coordinatorArtifacts.CoordinatorRegistry, + provider, + txDefaults, + allArtifacts, + ); + + // Coordinator + const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync( + coordinatorArtifacts.Coordinator, + provider, + txDefaults, + allArtifacts, + exchange.address, + chainId, + ); + + // Dev Utils + const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( + devUtilsArtifacts.DevUtils, + devUtilsArtifacts, + provider, + txDefaults, + allArtifacts, + exchange.address, + NULL_ADDRESS, + NULL_ADDRESS, + ); + + // tslint:disable-next-line:no-unused-variable + const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync( + erc1155Artifacts.ERC1155Mintable, + provider, + txDefaults, + allArtifacts, + ); + + const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync( + assetProxyArtifacts.ERC20BridgeProxy, + provider, + txDefaults, + allArtifacts, + ); await exchange.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults); + await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); + await erc20BridgeProxy.addAuthorizedAddress(multiAssetProxy.address).awaitTransactionSuccessAsync(txDefaults); + await multiAssetProxy.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults); - return [erc20Proxy, erc721Proxy, erc1155Proxy, staticCallProxy, multiAssetProxy, erc20BridgeProxy]; -} - -async function _migrateStakingAsync( - exchange: ExchangeContract, - erc20Proxy: ERC20ProxyContract, - zrxTokenAddress: string, - etherTokenAddress: string, - provider: ZeroExProvider, - txDefaults: TxData, -): Promise<[ZrxVaultContract, TestStakingContract, StakingProxyContract]> { + const zrxProxy = erc20Proxy.address; const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync( stakingArtifacts.ZrxVault, provider, txDefaults, allArtifacts, - erc20Proxy.address, - zrxTokenAddress, + zrxProxy, + zrxToken.address, ); // Note we use TestStakingContract as the deployed bytecode of a StakingContract @@ -364,7 +252,7 @@ async function _migrateStakingAsync( provider, txDefaults, allArtifacts, - etherTokenAddress, + etherToken.address, zrxVault.address, ); @@ -390,25 +278,57 @@ async function _migrateStakingAsync( await stakingLogic.addAuthorizedAddress(txDefaults.from).awaitTransactionSuccessAsync(txDefaults); await stakingLogic.addExchangeAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); - return [zrxVault, stakingLogic, stakingProxy]; -} + // Forwarder + // Deployed after Exchange and Staking is configured as it queries + // in the constructor + const { exchangeV2: exchangeV2Address } = getContractAddressesForChainOrThrow(chainId.toNumber()); + const forwarder = await ForwarderContract.deployFrom0xArtifactAsync( + forwarderArtifacts.Forwarder, + provider, + txDefaults, + allArtifacts, + exchange.address, + exchangeV2Address || NULL_ADDRESS, + etherToken.address, + ); + + // JAM + // tslint:disable-next-line:no-unused-variable + const jamToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync( + erc20Artifacts.DummyERC20Token, + provider, + txDefaults, + allArtifacts, + 'JAM Token', + 'JAM', + new BigNumber(18), + new BigNumber(1000000000000000000000000000), + ); + + // Exchange Proxy ////////////////////////////////////////////////////////// + + const bridgeAdapter = await BridgeAdapterContract.deployFrom0xArtifactAsync( + exchangeProxyArtifacts.BridgeAdapter, + provider, + txDefaults, + allArtifacts, + { + balancerBridge: NULL_ADDRESS, + curveBridge: NULL_ADDRESS, + kyberBridge: NULL_ADDRESS, + mStableBridge: NULL_ADDRESS, + oasisBridge: NULL_ADDRESS, + uniswapBridge: NULL_ADDRESS, + uniswapV2Bridge: NULL_ADDRESS, + kyberNetworkProxy: NULL_ADDRESS, + oasis: NULL_ADDRESS, + uniswapV2Router: NULL_ADDRESS, + uniswapExchangeFactory: NULL_ADDRESS, + mStable: NULL_ADDRESS, + weth: etherToken.address, + }, + ); -async function _migrateExchangeProxyAsync( - exchange: ExchangeContract, - etherTokenAddress: string, - provider: ZeroExProvider, - txDefaults: TxData, -): Promise< - [ - ZeroExContract, - FillQuoteTransformerContract, - PayTakerTransformerContract, - WethTransformerContract, - AffiliateFeeTransformerContract, - string, - string - ] -> { const exchangeProxy = await fullMigrateExchangeProxyAsync(txDefaults.from, provider, txDefaults); const exchangeProxyAllowanceTargetAddress = await new ITokenSpenderContract( exchangeProxy.address, @@ -428,6 +348,7 @@ async function _migrateExchangeProxyAsync( txDefaults, allArtifacts, exchange.address, + bridgeAdapter.address, ); const payTakerTransformer = await PayTakerTransformerContract.deployFrom0xArtifactAsync( exchangeProxyArtifacts.PayTakerTransformer, @@ -440,7 +361,7 @@ async function _migrateExchangeProxyAsync( provider, txDefaults, allArtifacts, - etherTokenAddress, + etherToken.address, ); const affiliateFeeTransformer = await AffiliateFeeTransformerContract.deployFrom0xArtifactAsync( exchangeProxyArtifacts.AffiliateFeeTransformer, @@ -449,42 +370,55 @@ async function _migrateExchangeProxyAsync( allArtifacts, ); - return [ - exchangeProxy, - fillQuoteTransformer, - payTakerTransformer, - wethTransformer, - affiliateFeeTransformer, - exchangeProxyFlashWalletAddress, - exchangeProxyAllowanceTargetAddress, - ]; -} - -async function _migrateDummyTokensAsync(provider: ZeroExProvider, txDefaults: TxData): Promise { - // Dummy ERC20 tokens - for (const token of erc20TokenInfo) { - const totalSupply = new BigNumber(1000000000000000000000000000); - await DummyERC20TokenContract.deployFrom0xArtifactAsync( - erc20Artifacts.DummyERC20Token, - provider, - txDefaults, - allArtifacts, - token.name, - token.symbol, - token.decimals, - totalSupply, - ); - } - - // Dummy ERC721 token - await DummyERC721TokenContract.deployFrom0xArtifactAsync( - erc721Artifacts.DummyERC721Token, - provider, - txDefaults, - allArtifacts, - erc721TokenInfo[0].name, - erc721TokenInfo[0].symbol, - ); + const contractAddresses = { + erc20Proxy: erc20Proxy.address, + erc721Proxy: erc721Proxy.address, + erc1155Proxy: erc1155Proxy.address, + zrxToken: zrxToken.address, + etherToken: etherToken.address, + exchange: exchange.address, + assetProxyOwner: NULL_ADDRESS, + erc20BridgeProxy: erc20BridgeProxy.address, + zeroExGovernor: NULL_ADDRESS, + forwarder: forwarder.address, + coordinatorRegistry: coordinatorRegistry.address, + coordinator: coordinator.address, + multiAssetProxy: multiAssetProxy.address, + staticCallProxy: staticCallProxy.address, + devUtils: devUtils.address, + exchangeV2: exchangeV2Address || NULL_ADDRESS, + 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, + exchangeProxyGovernor: NULL_ADDRESS, + mStableBridge: NULL_ADDRESS, + exchangeProxy: exchangeProxy.address, + exchangeProxyAllowanceTarget: exchangeProxyAllowanceTargetAddress, + exchangeProxyTransformerDeployer: txDefaults.from, + exchangeProxyFlashWallet: exchangeProxyFlashWalletAddress, + transformers: { + wethTransformer: wethTransformer.address, + payTakerTransformer: payTakerTransformer.address, + fillQuoteTransformer: fillQuoteTransformer.address, + affiliateFeeTransformer: affiliateFeeTransformer.address, + }, + }; + return contractAddresses; } let _cachedContractAddresses: ContractAddresses; @@ -507,4 +441,3 @@ export async function runMigrationsOnceAsync( _cachedContractAddresses = await runMigrationsAsync(provider, txDefaults); return _cachedContractAddresses; } -// tslint:disable-next-line: max-file-line-count diff --git a/tsconfig.json b/tsconfig.json index 178c0cd9fb..e68f896893 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,6 @@ "typeRoots": ["node_modules/@0x/typescript-typings/types", "node_modules/@types"], "strict": true, // These settings are required for TypeScript project references - "composite": true, "declaration": true, "declarationMap": true, "sourceMap": true