From 3947d37cb8148c21d3a8da03b5519c5d3ec9769f Mon Sep 17 00:00:00 2001 From: Lawrence Forman Date: Fri, 31 Jan 2020 15:56:08 -0500 Subject: [PATCH] Cherry pick `DevUtils` refactor code from #2456 --- contracts/dev-utils/CHANGELOG.json | 13 + .../dev-utils/contracts/src/Addresses.sol | 51 + .../dev-utils/contracts/src/AssetBalance.sol | 374 +++++ .../dev-utils/contracts/src/DevUtils.sol | 20 +- .../contracts/src/EthBalanceChecker.sol | 2 +- .../contracts/src/ExternalFunctions.sol | 322 ++++ .../dev-utils/contracts/src/LibAssetData.sol | 384 +---- .../src/LibOrderTransferSimulation.sol | 227 +++ .../contracts/src/LibTransactionDecoder.sol | 4 +- .../contracts/src/OrderValidationUtils.sol | 89 +- contracts/dev-utils/package.json | 11 +- contracts/dev-utils/src/artifacts.ts | 2 + contracts/dev-utils/src/index.ts | 2 +- contracts/dev-utils/src/wrappers.ts | 1 + contracts/dev-utils/test/artifacts.ts | 8 + contracts/dev-utils/test/wrappers.ts | 4 + contracts/dev-utils/tsconfig.json | 5 + contracts/erc20/CHANGELOG.json | 4 +- .../erc20/contracts/src/LibERC20Token.sol | 47 +- contracts/integrations/CHANGELOG.json | 4 + .../test/dev-utils/dev_utils_mainnet_test.ts | 3 +- .../test/dev-utils/get_order_hash.ts | 3 +- .../test/dev-utils/lib_asset_data.ts | 219 ++- .../test/dev-utils/lib_transaction_decoder.ts | 52 +- .../test/framework/deployment_manager.ts | 3 +- .../templates/TypeScript/contract.handlebars | 1 + packages/contract-addresses/CHANGELOG.json | 8 + packages/contract-addresses/addresses.json | 17 +- packages/contract-addresses/src/index.ts | 1 - packages/contract-artifacts/CHANGELOG.json | 13 + .../artifacts/DevUtils.json | 367 +--- .../artifacts/LibTransactionDecoder.json | 84 - packages/contract-artifacts/src/index.ts | 2 - packages/contract-artifacts/tsconfig.json | 1 - packages/contract-wrappers/CHANGELOG.json | 6 +- .../src/contract_wrappers.ts | 10 - .../src/generated-wrappers/coordinator.ts | 125 +- .../src/generated-wrappers/dev_utils.ts | 1469 ++++++++--------- .../src/generated-wrappers/erc20_token.ts | 99 +- .../src/generated-wrappers/erc721_token.ts | 99 +- .../src/generated-wrappers/exchange.ts | 100 +- .../src/generated-wrappers/forwarder.ts | 111 +- .../src/generated-wrappers/i_asset_data.ts | 95 +- .../i_erc20_bridge_sampler.ts | 191 ++- .../lib_transaction_decoder.ts | 367 ---- .../src/generated-wrappers/staking.ts | 99 +- .../src/generated-wrappers/staking_proxy.ts | 107 +- .../src/generated-wrappers/weth9.ts | 99 +- packages/contract-wrappers/src/index.ts | 1 - packages/dev-utils/CHANGELOG.json | 9 + packages/migrations/CHANGELOG.json | 17 + packages/migrations/package.json | 1 - packages/migrations/src/migration.ts | 121 +- packages/migrations/src/testnet_migrations.ts | 16 +- 54 files changed, 3231 insertions(+), 2259 deletions(-) create mode 100644 contracts/dev-utils/contracts/src/Addresses.sol create mode 100644 contracts/dev-utils/contracts/src/AssetBalance.sol create mode 100644 contracts/dev-utils/contracts/src/ExternalFunctions.sol create mode 100644 contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol delete mode 100644 packages/contract-artifacts/artifacts/LibTransactionDecoder.json delete mode 100644 packages/contract-wrappers/src/generated-wrappers/lib_transaction_decoder.ts diff --git a/contracts/dev-utils/CHANGELOG.json b/contracts/dev-utils/CHANGELOG.json index d5f6e5e981..e65b8b5345 100644 --- a/contracts/dev-utils/CHANGELOG.json +++ b/contracts/dev-utils/CHANGELOG.json @@ -1,4 +1,17 @@ [ + { + "version": "1.1.0", + "changes": [ + { + "note": "Refactor mixins into public libraries.", + "pr": 2464 + }, + { + "note": "Remove `LibTransactionDecoder` export", + "pr": 2464 + } + ] + }, { "timestamp": 1579682890, "version": "1.0.4", diff --git a/contracts/dev-utils/contracts/src/Addresses.sol b/contracts/dev-utils/contracts/src/Addresses.sol new file mode 100644 index 0000000000..3cd41a329c --- /dev/null +++ b/contracts/dev-utils/contracts/src/Addresses.sol @@ -0,0 +1,51 @@ +/* + + 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.16; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol"; +import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; +import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; + + +// solhint-disable no-empty-blocks +contract Addresses is + DeploymentConstants +{ + address public exchangeAddress; + address public erc20ProxyAddress; + address public erc721ProxyAddress; + address public erc1155ProxyAddress; + address public staticCallProxyAddress; + address public chaiBridgeAddress; + + constructor ( + address exchange_, + address chaiBridge_ + ) + public + { + exchangeAddress = exchange_; + chaiBridgeAddress = chaiBridge_; + erc20ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC20Token.selector); + erc721ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC721Token.selector); + erc1155ProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector); + staticCallProxyAddress = IExchange(exchange_).getAssetProxy(IAssetData(address(0)).StaticCall.selector); + } +} diff --git a/contracts/dev-utils/contracts/src/AssetBalance.sol b/contracts/dev-utils/contracts/src/AssetBalance.sol new file mode 100644 index 0000000000..cc72becb46 --- /dev/null +++ b/contracts/dev-utils/contracts/src/AssetBalance.sol @@ -0,0 +1,374 @@ +/* + + 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.16; +pragma experimental ABIEncoderV2; + +import "@0x/contracts-utils/contracts/src/LibBytes.sol"; +import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol"; +import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol"; +import "@0x/contracts-erc20/contracts/src/LibERC20Token.sol"; +import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol"; +import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol"; +import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; +import "./Addresses.sol"; +import "./LibAssetData.sol"; + + +contract AssetBalance is + Addresses +{ + // 2^256 - 1 + uint256 constant internal _MAX_UINT256 = uint256(-1); + + using LibBytes for bytes; + + /// @dev Returns the owner's balance of the assets(s) specified in + /// assetData. When the asset data contains multiple assets (eg in + /// ERC1155 or Multi-Asset), the return value indicates how many + /// complete "baskets" of those assets are owned by owner. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Details of asset, encoded per the AssetProxy contract specification. + /// @return Number of assets (or asset baskets) held by owner. + function getBalance(address ownerAddress, bytes memory assetData) + public + returns (uint256 balance) + { + // Get id of AssetProxy contract + bytes4 assetProxyId = assetData.readBytes4(0); + + if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) { + // Get ERC20 token address + address tokenAddress = assetData.readAddress(16); + balance = LibERC20Token.balanceOf(tokenAddress, ownerAddress); + + } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) { + // Get ERC721 token address and id + (, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData); + + // Check if id is owned by ownerAddress + bytes memory ownerOfCalldata = abi.encodeWithSelector( + IERC721Token(address(0)).ownerOf.selector, + tokenId + ); + + (bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata); + address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0); + balance = currentOwnerAddress == ownerAddress ? 1 : 0; + + } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) { + // Get ERC1155 token address, array of ids, and array of values + (, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = LibAssetData.decodeERC1155AssetData(assetData); + + uint256 length = tokenIds.length; + for (uint256 i = 0; i != length; i++) { + // Skip over the token if the corresponding value is 0. + if (tokenValues[i] == 0) { + continue; + } + + // Encode data for `balanceOf(ownerAddress, tokenIds[i]) + bytes memory balanceOfData = abi.encodeWithSelector( + IERC1155(address(0)).balanceOf.selector, + ownerAddress, + tokenIds[i] + ); + + // Query balance + (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData); + uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0; + + // Scale total balance down by corresponding value in assetData + uint256 scaledBalance = totalBalance / tokenValues[i]; + if (scaledBalance == 0) { + return 0; + } + if (scaledBalance < balance || balance == 0) { + balance = scaledBalance; + } + } + + } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) { + // Encode data for `staticCallProxy.transferFrom(assetData,...)` + bytes memory transferFromData = abi.encodeWithSelector( + IAssetProxy(address(0)).transferFrom.selector, + assetData, + address(0), // `from` address is not used + address(0), // `to` address is not used + 0 // `amount` is not used + ); + + // Check if staticcall would be successful + (bool success,) = staticCallProxyAddress.staticcall(transferFromData); + + // Success means that the staticcall can be made an unlimited amount of times + balance = success ? _MAX_UINT256 : 0; + + } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) { + // Get address of ERC20 token and bridge contract + (, address tokenAddress, address bridgeAddress, ) = LibAssetData.decodeERC20BridgeAssetData(assetData); + if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) { + uint256 chaiBalance = LibERC20Token.balanceOf(_getChaiAddress(), ownerAddress); + // Calculate Dai balance + balance = _convertChaiToDaiAmount(chaiBalance); + } + // Balance will be 0 if bridge is not supported + + } else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) { + // Get array of values and array of assetDatas + (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData); + + uint256 length = nestedAssetData.length; + for (uint256 i = 0; i != length; i++) { + // Skip over the asset if the corresponding amount is 0. + if (assetAmounts[i] == 0) { + continue; + } + + // Query balance of individual assetData + uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]); + + // Scale total balance down by corresponding value in assetData + uint256 scaledBalance = totalBalance / assetAmounts[i]; + if (scaledBalance == 0) { + return 0; + } + if (scaledBalance < balance || balance == 0) { + balance = scaledBalance; + } + } + } + + // Balance will be 0 if assetProxyId is unknown + return balance; + } + + /// @dev Calls getBalance() for each element of assetData. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. + /// @return Array of asset balances from getBalance(), with each element + /// corresponding to the same-indexed element in the assetData input. + function getBatchBalances(address ownerAddress, bytes[] memory assetData) + public + returns (uint256[] memory balances) + { + uint256 length = assetData.length; + balances = new uint256[](length); + for (uint256 i = 0; i != length; i++) { + balances[i] = getBalance(ownerAddress, assetData[i]); + } + return balances; + } + + /// @dev Returns the number of asset(s) (described by assetData) that + /// the corresponding AssetProxy contract is authorized to spend. When the asset data contains + /// multiple assets (eg for Multi-Asset), the return value indicates + /// how many complete "baskets" of those assets may be spent by all of the corresponding + /// AssetProxy contracts. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Details of asset, encoded per the AssetProxy contract specification. + /// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend. + function getAssetProxyAllowance(address ownerAddress, bytes memory assetData) + public + returns (uint256 allowance) + { + // Get id of AssetProxy contract + bytes4 assetProxyId = assetData.readBytes4(0); + + if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) { + // Get array of values and array of assetDatas + (, uint256[] memory amounts, bytes[] memory nestedAssetData) = LibAssetData.decodeMultiAssetData(assetData); + + uint256 length = nestedAssetData.length; + for (uint256 i = 0; i != length; i++) { + // Skip over the asset if the corresponding amount is 0. + if (amounts[i] == 0) { + continue; + } + + // Query allowance of individual assetData + uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]); + + // Scale total allowance down by corresponding value in assetData + uint256 scaledAllowance = totalAllowance / amounts[i]; + if (scaledAllowance == 0) { + return 0; + } + if (scaledAllowance < allowance || allowance == 0) { + allowance = scaledAllowance; + } + } + return allowance; + } + + if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) { + // Get ERC20 token address + address tokenAddress = assetData.readAddress(16); + allowance = LibERC20Token.allowance(tokenAddress, ownerAddress, erc20ProxyAddress); + + } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) { + // Get ERC721 token address and id + (, address tokenAddress, uint256 tokenId) = LibAssetData.decodeERC721AssetData(assetData); + + // Encode data for `isApprovedForAll(ownerAddress, erc721ProxyAddress)` + bytes memory isApprovedForAllData = abi.encodeWithSelector( + IERC721Token(address(0)).isApprovedForAll.selector, + ownerAddress, + erc721ProxyAddress + ); + + (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData); + + // If not approved for all, call `getApproved(tokenId)` + if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) { + // Encode data for `getApproved(tokenId)` + bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId); + (success, returnData) = tokenAddress.staticcall(getApprovedData); + + // Allowance is 1 if successful and the approved address is the ERC721Proxy + allowance = success && returnData.length == 32 && returnData.readAddress(12) == erc721ProxyAddress ? 1 : 0; + } else { + // Allowance is 2^256 - 1 if `isApprovedForAll` returned true + allowance = _MAX_UINT256; + } + + } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) { + // Get ERC1155 token address + (, address tokenAddress, , , ) = LibAssetData.decodeERC1155AssetData(assetData); + + // Encode data for `isApprovedForAll(ownerAddress, erc1155ProxyAddress)` + bytes memory isApprovedForAllData = abi.encodeWithSelector( + IERC1155(address(0)).isApprovedForAll.selector, + ownerAddress, + erc1155ProxyAddress + ); + + // Query allowance + (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData); + allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0; + + } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) { + // The StaticCallProxy does not require any approvals + allowance = _MAX_UINT256; + + } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) { + // Get address of ERC20 token and bridge contract + (, address tokenAddress, address bridgeAddress,) = LibAssetData.decodeERC20BridgeAssetData(assetData); + if (tokenAddress == _getDaiAddress() && bridgeAddress == chaiBridgeAddress) { + uint256 chaiAllowance = LibERC20Token.allowance(_getChaiAddress(), ownerAddress, chaiBridgeAddress); + // Dai allowance is unlimited if Chai allowance is unlimited + allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance); + } + // Allowance will be 0 if bridge is not supported + } + + // Allowance will be 0 if the assetProxyId is unknown + return allowance; + } + + /// @dev Calls getAssetProxyAllowance() for each element of assetData. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. + /// @return An array of asset allowances from getAllowance(), with each + /// element corresponding to the same-indexed element in the assetData input. + function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData) + public + returns (uint256[] memory allowances) + { + uint256 length = assetData.length; + allowances = new uint256[](length); + for (uint256 i = 0; i != length; i++) { + allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]); + } + return allowances; + } + + /// @dev Calls getBalance() and getAllowance() for assetData. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Details of asset, encoded per the AssetProxy contract specification. + /// @return Number of assets (or asset baskets) held by owner, and number + /// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend. + function getBalanceAndAssetProxyAllowance( + address ownerAddress, + bytes memory assetData + ) + public + returns (uint256 balance, uint256 allowance) + { + balance = getBalance(ownerAddress, assetData); + allowance = getAssetProxyAllowance(ownerAddress, assetData); + return (balance, allowance); + } + + /// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData. + /// @param ownerAddress Owner of the assets specified by assetData. + /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. + /// @return An array of asset balances from getBalance(), and an array of + /// asset allowances from getAllowance(), with each element + /// corresponding to the same-indexed element in the assetData input. + function getBatchBalancesAndAssetProxyAllowances( + address ownerAddress, + bytes[] memory assetData + ) + public + returns (uint256[] memory balances, uint256[] memory allowances) + { + balances = getBatchBalances(ownerAddress, assetData); + allowances = getBatchAssetProxyAllowances(ownerAddress, assetData); + return (balances, allowances); + } + + /// @dev Converts an amount of Chai into its equivalent Dai amount. + /// Also accumulates Dai from DSR if called after the last time it was collected. + /// @param chaiAmount Amount of Chai to converts. + function _convertChaiToDaiAmount(uint256 chaiAmount) + internal + returns (uint256 daiAmount) + { + PotLike pot = IChai(_getChaiAddress()).pot(); + // Accumulate savings if called after last time savings were collected + // solhint-disable-next-line not-rely-on-time + uint256 chiMultiplier = (now > pot.rho()) + ? pot.drip() + : pot.chi(); + daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount); + return daiAmount; + } + + /// @dev Returns an order MAKER's balance of the assets(s) specified in + /// makerAssetData. Unlike `getBalanceAndAssetProxyAllowance()`, this + /// can handle maker asset types that depend on taker tokens being + /// transferred to the maker first. + /// @param order The order. + /// @return balance Quantity of assets transferrable from maker to taker. + function _getConvertibleMakerBalanceAndAssetProxyAllowance( + LibOrder.Order memory order + ) + internal + returns (uint256 balance, uint256 allowance) + { + if (order.makerAssetData.length < 4) { + return (0, 0); + } + return ( + getBalance(order.makerAddress, order.makerAssetData), + getAssetProxyAllowance(order.makerAddress, order.makerAssetData) + ); + } +} diff --git a/contracts/dev-utils/contracts/src/DevUtils.sol b/contracts/dev-utils/contracts/src/DevUtils.sol index f0913ab848..45ce184646 100644 --- a/contracts/dev-utils/contracts/src/DevUtils.sol +++ b/contracts/dev-utils/contracts/src/DevUtils.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.5.5; +pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; import "@0x/contracts-exchange-libs/contracts/src/LibEIP712ExchangeDomain.sol"; @@ -24,27 +24,29 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibZeroExTransaction.sol"; import "@0x/contracts-utils/contracts/src/LibEIP712.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; +import "./Addresses.sol"; import "./OrderValidationUtils.sol"; -import "./OrderTransferSimulationUtils.sol"; import "./EthBalanceChecker.sol"; +import "./ExternalFunctions.sol"; // solhint-disable no-empty-blocks contract DevUtils is + Addresses, OrderValidationUtils, LibEIP712ExchangeDomain, - EthBalanceChecker + EthBalanceChecker, + ExternalFunctions { constructor ( - address _exchange, - address _chaiBridge + address exchange_, + address chaiBridge_ ) public - OrderValidationUtils( - _exchange, - _chaiBridge + Addresses( + exchange_, + chaiBridge_ ) - OrderTransferSimulationUtils(_exchange) LibEIP712ExchangeDomain(uint256(0), address(0)) // null args because because we only use constants {} diff --git a/contracts/dev-utils/contracts/src/EthBalanceChecker.sol b/contracts/dev-utils/contracts/src/EthBalanceChecker.sol index 88ec3c0255..48e0215692 100644 --- a/contracts/dev-utils/contracts/src/EthBalanceChecker.sol +++ b/contracts/dev-utils/contracts/src/EthBalanceChecker.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.5.5; +pragma solidity ^0.5.16; contract EthBalanceChecker { diff --git a/contracts/dev-utils/contracts/src/ExternalFunctions.sol b/contracts/dev-utils/contracts/src/ExternalFunctions.sol new file mode 100644 index 0000000000..e9e1443404 --- /dev/null +++ b/contracts/dev-utils/contracts/src/ExternalFunctions.sol @@ -0,0 +1,322 @@ +/* + + 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.16; +pragma experimental ABIEncoderV2; + +import "./Addresses.sol"; +import "./LibAssetData.sol"; +import "./LibTransactionDecoder.sol"; +import "./LibOrderTransferSimulation.sol"; + + +contract ExternalFunctions is + Addresses +{ + + /// @dev Decodes the call data for an Exchange contract method call. + /// @param transactionData ABI-encoded calldata for an Exchange + /// contract method call. + /// @return The name of the function called, and the parameters it was + /// given. For single-order fills and cancels, the arrays will have + /// just one element. + function decodeZeroExTransactionData(bytes memory transactionData) + public + pure + returns( + string memory functionName, + LibOrder.Order[] memory orders, + uint256[] memory takerAssetFillAmounts, + bytes[] memory signatures + ) + { + return LibTransactionDecoder.decodeZeroExTransactionData(transactionData); + } + + /// @dev Decode AssetProxy identifier + /// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset. + /// @return The AssetProxy identifier + function decodeAssetProxyId(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId + ) + { + return LibAssetData.decodeAssetProxyId(assetData); + } + + /// @dev Encode ERC-20 asset data into the format described in the AssetProxy contract specification. + /// @param tokenAddress The address of the ERC-20 contract hosting the asset to be traded. + /// @return AssetProxy-compliant data describing the asset. + function encodeERC20AssetData(address tokenAddress) + public + pure + returns (bytes memory assetData) + { + return LibAssetData.encodeERC20AssetData(tokenAddress); + } + + /// @dev Decode ERC-20 asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant asset data describing an ERC-20 asset. + /// @return The AssetProxy identifier, and the address of the ERC-20 + /// contract hosting this asset. + function decodeERC20AssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + address tokenAddress + ) + { + return LibAssetData.decodeERC20AssetData(assetData); + } + + /// @dev Encode ERC-721 asset data into the format described in the AssetProxy specification. + /// @param tokenAddress The address of the ERC-721 contract hosting the asset to be traded. + /// @param tokenId The identifier of the specific asset to be traded. + /// @return AssetProxy-compliant asset data describing the asset. + function encodeERC721AssetData(address tokenAddress, uint256 tokenId) + public + pure + returns (bytes memory assetData) + { + return LibAssetData.encodeERC721AssetData(tokenAddress, tokenId); + } + + /// @dev Decode ERC-721 asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant asset data describing an ERC-721 asset. + /// @return The ERC-721 AssetProxy identifier, the address of the ERC-721 + /// contract hosting this asset, and the identifier of the specific + /// asset to be traded. + function decodeERC721AssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + address tokenAddress, + uint256 tokenId + ) + { + return LibAssetData.decodeERC721AssetData(assetData); + } + + /// @dev Encode ERC-1155 asset data into the format described in the AssetProxy contract specification. + /// @param tokenAddress The address of the ERC-1155 contract hosting the asset(s) to be traded. + /// @param tokenIds The identifiers of the specific assets to be traded. + /// @param tokenValues The amounts of each asset to be traded. + /// @param callbackData Data to be passed to receiving contracts when a transfer is performed. + /// @return AssetProxy-compliant asset data describing the set of assets. + function encodeERC1155AssetData( + address tokenAddress, + uint256[] memory tokenIds, + uint256[] memory tokenValues, + bytes memory callbackData + ) + public + pure + returns (bytes memory assetData) + { + return LibAssetData.encodeERC1155AssetData( + tokenAddress, + tokenIds, + tokenValues, + callbackData + ); + } + + /// @dev Decode ERC-1155 asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant asset data describing an ERC-1155 set of assets. + /// @return The ERC-1155 AssetProxy identifier, the address of the ERC-1155 + /// contract hosting the assets, an array of the identifiers of the + /// assets to be traded, an array of asset amounts to be traded, and + /// callback data. Each element of the arrays corresponds to the + /// same-indexed element of the other array. Return values specified as + /// `memory` are returned as pointers to locations within the memory of + /// the input parameter `assetData`. + function decodeERC1155AssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + address tokenAddress, + uint256[] memory tokenIds, + uint256[] memory tokenValues, + bytes memory callbackData + ) + { + return LibAssetData.decodeERC1155AssetData(assetData); + } + + /// @dev Encode data for multiple assets, per the AssetProxy contract specification. + /// @param amounts The amounts of each asset to be traded. + /// @param nestedAssetData AssetProxy-compliant data describing each asset to be traded. + /// @return AssetProxy-compliant data describing the set of assets. + function encodeMultiAssetData(uint256[] memory amounts, bytes[] memory nestedAssetData) + public + pure + returns (bytes memory assetData) + { + return LibAssetData.encodeMultiAssetData(amounts, nestedAssetData); + } + + /// @dev Decode multi-asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant data describing a multi-asset basket. + /// @return The Multi-Asset AssetProxy identifier, an array of the amounts + /// of the assets to be traded, and an array of the + /// AssetProxy-compliant data describing each asset to be traded. Each + /// element of the arrays corresponds to the same-indexed element of the other array. + function decodeMultiAssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + uint256[] memory amounts, + bytes[] memory nestedAssetData + ) + { + return LibAssetData.decodeMultiAssetData(assetData); + } + + /// @dev Encode StaticCall asset data into the format described in the AssetProxy contract specification. + /// @param staticCallTargetAddress Target address of StaticCall. + /// @param staticCallData Data that will be passed to staticCallTargetAddress in the StaticCall. + /// @param expectedReturnDataHash Expected Keccak-256 hash of the StaticCall return data. + /// @return AssetProxy-compliant asset data describing the set of assets. + function encodeStaticCallAssetData( + address staticCallTargetAddress, + bytes memory staticCallData, + bytes32 expectedReturnDataHash + ) + public + pure + returns (bytes memory assetData) + { + return LibAssetData.encodeStaticCallAssetData( + staticCallTargetAddress, + staticCallData, + expectedReturnDataHash + ); + } + + /// @dev Decode StaticCall asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant asset data describing a StaticCall asset + /// @return The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be + /// passed to the target address, and the expected Keccak-256 hash of the static call return data. + function decodeStaticCallAssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + address staticCallTargetAddress, + bytes memory staticCallData, + bytes32 expectedReturnDataHash + ) + { + return LibAssetData.decodeStaticCallAssetData(assetData); + } + + /// @dev Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification. + /// @param assetData AssetProxy-compliant asset data describing an ERC20Bridge asset + /// @return The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address + /// of the bridge contract, and extra data to be passed to the bridge contract. + function decodeERC20BridgeAssetData(bytes memory assetData) + public + pure + returns ( + bytes4 assetProxyId, + address tokenAddress, + address bridgeAddress, + bytes memory bridgeData + ) + { + return LibAssetData.decodeERC20BridgeAssetData(assetData); + } + + /// @dev Reverts if assetData is not of a valid format for its given proxy id. + /// @param assetData AssetProxy compliant asset data. + function revertIfInvalidAssetData(bytes memory assetData) + public + pure + { + return LibAssetData.revertIfInvalidAssetData(assetData); + } + + /// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer. + /// @param order The order to simulate transfers for. + /// @param takerAddress The address of the taker that will fill the order. + /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill. + /// @return The index of the first failed transfer (or 4 if all transfers are successful). + function getSimulatedOrderMakerTransferResults( + LibOrder.Order memory order, + address takerAddress, + uint256 takerAssetFillAmount + ) + public + returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults) + { + return LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults( + exchangeAddress, + order, + takerAddress, + takerAssetFillAmount + ); + } + + /// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer. + /// @param order The order to simulate transfers for. + /// @param takerAddress The address of the taker that will fill the order. + /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill. + /// @return The index of the first failed transfer (or 4 if all transfers are successful). + function getSimulatedOrderTransferResults( + LibOrder.Order memory order, + address takerAddress, + uint256 takerAssetFillAmount + ) + public + returns (LibOrderTransferSimulation.OrderTransferResults orderTransferResults) + { + return LibOrderTransferSimulation.getSimulatedOrderTransferResults( + exchangeAddress, + order, + takerAddress, + takerAssetFillAmount + ); + } + + /// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer. + /// @param orders Array of orders to individually simulate transfers for. + /// @param takerAddresses Array of addresses of takers that will fill each order. + /// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order. + /// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order. + function getSimulatedOrdersTransferResults( + LibOrder.Order[] memory orders, + address[] memory takerAddresses, + uint256[] memory takerAssetFillAmounts + ) + public + returns (LibOrderTransferSimulation.OrderTransferResults[] memory orderTransferResults) + { + return LibOrderTransferSimulation.getSimulatedOrdersTransferResults( + exchangeAddress, + orders, + takerAddresses, + takerAssetFillAmounts + ); + } +} diff --git a/contracts/dev-utils/contracts/src/LibAssetData.sol b/contracts/dev-utils/contracts/src/LibAssetData.sol index 95aa3bee26..2408c9dae4 100644 --- a/contracts/dev-utils/contracts/src/LibAssetData.sol +++ b/contracts/dev-utils/contracts/src/LibAssetData.sol @@ -16,357 +16,17 @@ */ -pragma solidity ^0.5.5; +pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; -import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetData.sol"; -import "@0x/contracts-asset-proxy/contracts/src/interfaces/IAssetProxy.sol"; -import "@0x/contracts-erc20/contracts/src/interfaces/IERC20Token.sol"; -import "@0x/contracts-erc721/contracts/src/interfaces/IERC721Token.sol"; -import "@0x/contracts-erc1155/contracts/src/interfaces/IERC1155.sol"; -import "@0x/contracts-asset-proxy/contracts/src/interfaces/IChai.sol"; -import "@0x/contracts-utils/contracts/src/DeploymentConstants.sol"; -import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; -contract LibAssetData is - DeploymentConstants -{ - // 2^256 - 1 - uint256 constant internal _MAX_UINT256 = uint256(-1); +library LibAssetData { using LibBytes for bytes; - // solhint-disable var-name-mixedcase - IExchange internal _EXCHANGE; - address internal _ERC20_PROXY_ADDRESS; - address internal _ERC721_PROXY_ADDRESS; - address internal _ERC1155_PROXY_ADDRESS; - address internal _STATIC_CALL_PROXY_ADDRESS; - address internal _CHAI_BRIDGE_ADDRESS; - // solhint-enable var-name-mixedcase - - constructor ( - address _exchange, - address _chaiBridge - ) - public - { - _EXCHANGE = IExchange(_exchange); - _ERC20_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC20Token.selector); - _ERC721_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC721Token.selector); - _ERC1155_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).ERC1155Assets.selector); - _STATIC_CALL_PROXY_ADDRESS = _EXCHANGE.getAssetProxy(IAssetData(address(0)).StaticCall.selector); - _CHAI_BRIDGE_ADDRESS = _chaiBridge; - } - - /// @dev Returns the owner's balance of the assets(s) specified in - /// assetData. When the asset data contains multiple assets (eg in - /// ERC1155 or Multi-Asset), the return value indicates how many - /// complete "baskets" of those assets are owned by owner. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Details of asset, encoded per the AssetProxy contract specification. - /// @return Number of assets (or asset baskets) held by owner. - function getBalance(address ownerAddress, bytes memory assetData) - public - returns (uint256 balance) - { - // Get id of AssetProxy contract - bytes4 assetProxyId = assetData.readBytes4(0); - - if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) { - // Get ERC20 token address - address tokenAddress = assetData.readAddress(16); - balance = _erc20BalanceOf(tokenAddress, ownerAddress); - - } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) { - // Get ERC721 token address and id - (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData); - - // Check if id is owned by ownerAddress - bytes memory ownerOfCalldata = abi.encodeWithSelector( - IERC721Token(address(0)).ownerOf.selector, - tokenId - ); - - (bool success, bytes memory returnData) = tokenAddress.staticcall(ownerOfCalldata); - address currentOwnerAddress = (success && returnData.length == 32) ? returnData.readAddress(12) : address(0); - balance = currentOwnerAddress == ownerAddress ? 1 : 0; - - } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) { - // Get ERC1155 token address, array of ids, and array of values - (, address tokenAddress, uint256[] memory tokenIds, uint256[] memory tokenValues,) = decodeERC1155AssetData(assetData); - - uint256 length = tokenIds.length; - for (uint256 i = 0; i != length; i++) { - // Skip over the token if the corresponding value is 0. - if (tokenValues[i] == 0) { - continue; - } - - // Encode data for `balanceOf(ownerAddress, tokenIds[i]) - bytes memory balanceOfData = abi.encodeWithSelector( - IERC1155(address(0)).balanceOf.selector, - ownerAddress, - tokenIds[i] - ); - - // Query balance - (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData); - uint256 totalBalance = success && returnData.length == 32 ? returnData.readUint256(0) : 0; - - // Scale total balance down by corresponding value in assetData - uint256 scaledBalance = totalBalance / tokenValues[i]; - if (scaledBalance == 0) { - return 0; - } - if (scaledBalance < balance || balance == 0) { - balance = scaledBalance; - } - } - - } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) { - // Encode data for `staticCallProxy.transferFrom(assetData,...)` - bytes memory transferFromData = abi.encodeWithSelector( - IAssetProxy(address(0)).transferFrom.selector, - assetData, - address(0), // `from` address is not used - address(0), // `to` address is not used - 0 // `amount` is not used - ); - - // Check if staticcall would be successful - (bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData); - - // Success means that the staticcall can be made an unlimited amount of times - balance = success ? _MAX_UINT256 : 0; - - } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) { - // Get address of ERC20 token and bridge contract - (, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData); - if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) { - uint256 chaiBalance = _erc20BalanceOf(_getChaiAddress(), ownerAddress); - // Calculate Dai balance - balance = _convertChaiToDaiAmount(chaiBalance); - } - // Balance will be 0 if bridge is not supported - - } else if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) { - // Get array of values and array of assetDatas - (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData); - - uint256 length = nestedAssetData.length; - for (uint256 i = 0; i != length; i++) { - // Skip over the asset if the corresponding amount is 0. - if (assetAmounts[i] == 0) { - continue; - } - - // Query balance of individual assetData - uint256 totalBalance = getBalance(ownerAddress, nestedAssetData[i]); - - // Scale total balance down by corresponding value in assetData - uint256 scaledBalance = totalBalance / assetAmounts[i]; - if (scaledBalance == 0) { - return 0; - } - if (scaledBalance < balance || balance == 0) { - balance = scaledBalance; - } - } - } - - // Balance will be 0 if assetProxyId is unknown - return balance; - } - - /// @dev Calls getBalance() for each element of assetData. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. - /// @return Array of asset balances from getBalance(), with each element - /// corresponding to the same-indexed element in the assetData input. - function getBatchBalances(address ownerAddress, bytes[] memory assetData) - public - returns (uint256[] memory balances) - { - uint256 length = assetData.length; - balances = new uint256[](length); - for (uint256 i = 0; i != length; i++) { - balances[i] = getBalance(ownerAddress, assetData[i]); - } - return balances; - } - - /// @dev Returns the number of asset(s) (described by assetData) that - /// the corresponding AssetProxy contract is authorized to spend. When the asset data contains - /// multiple assets (eg for Multi-Asset), the return value indicates - /// how many complete "baskets" of those assets may be spent by all of the corresponding - /// AssetProxy contracts. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Details of asset, encoded per the AssetProxy contract specification. - /// @return Number of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend. - function getAssetProxyAllowance(address ownerAddress, bytes memory assetData) - public - returns (uint256 allowance) - { - // Get id of AssetProxy contract - bytes4 assetProxyId = assetData.readBytes4(0); - - if (assetProxyId == IAssetData(address(0)).MultiAsset.selector) { - // Get array of values and array of assetDatas - (, uint256[] memory amounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData); - - uint256 length = nestedAssetData.length; - for (uint256 i = 0; i != length; i++) { - // Skip over the asset if the corresponding amount is 0. - if (amounts[i] == 0) { - continue; - } - - // Query allowance of individual assetData - uint256 totalAllowance = getAssetProxyAllowance(ownerAddress, nestedAssetData[i]); - - // Scale total allowance down by corresponding value in assetData - uint256 scaledAllowance = totalAllowance / amounts[i]; - if (scaledAllowance == 0) { - return 0; - } - if (scaledAllowance < allowance || allowance == 0) { - allowance = scaledAllowance; - } - } - return allowance; - } - - if (assetProxyId == IAssetData(address(0)).ERC20Token.selector) { - // Get ERC20 token address - address tokenAddress = assetData.readAddress(16); - - // Encode data for `allowance(ownerAddress, _ERC20_PROXY_ADDRESS)` - bytes memory allowanceData = abi.encodeWithSelector( - IERC20Token(address(0)).allowance.selector, - ownerAddress, - _ERC20_PROXY_ADDRESS - ); - - // Query allowance - (bool success, bytes memory returnData) = tokenAddress.staticcall(allowanceData); - allowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0; - - } else if (assetProxyId == IAssetData(address(0)).ERC721Token.selector) { - // Get ERC721 token address and id - (, address tokenAddress, uint256 tokenId) = decodeERC721AssetData(assetData); - - // Encode data for `isApprovedForAll(ownerAddress, _ERC721_PROXY_ADDRESS)` - bytes memory isApprovedForAllData = abi.encodeWithSelector( - IERC721Token(address(0)).isApprovedForAll.selector, - ownerAddress, - _ERC721_PROXY_ADDRESS - ); - - (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData); - - // If not approved for all, call `getApproved(tokenId)` - if (!success || returnData.length != 32 || returnData.readUint256(0) != 1) { - // Encode data for `getApproved(tokenId)` - bytes memory getApprovedData = abi.encodeWithSelector(IERC721Token(address(0)).getApproved.selector, tokenId); - (success, returnData) = tokenAddress.staticcall(getApprovedData); - - // Allowance is 1 if successful and the approved address is the ERC721Proxy - allowance = success && returnData.length == 32 && returnData.readAddress(12) == _ERC721_PROXY_ADDRESS ? 1 : 0; - } else { - // Allowance is 2^256 - 1 if `isApprovedForAll` returned true - allowance = _MAX_UINT256; - } - - } else if (assetProxyId == IAssetData(address(0)).ERC1155Assets.selector) { - // Get ERC1155 token address - (, address tokenAddress, , , ) = decodeERC1155AssetData(assetData); - - // Encode data for `isApprovedForAll(ownerAddress, _ERC1155_PROXY_ADDRESS)` - bytes memory isApprovedForAllData = abi.encodeWithSelector( - IERC1155(address(0)).isApprovedForAll.selector, - ownerAddress, - _ERC1155_PROXY_ADDRESS - ); - - // Query allowance - (bool success, bytes memory returnData) = tokenAddress.staticcall(isApprovedForAllData); - allowance = success && returnData.length == 32 && returnData.readUint256(0) == 1 ? _MAX_UINT256 : 0; - - } else if (assetProxyId == IAssetData(address(0)).StaticCall.selector) { - // The StaticCallProxy does not require any approvals - allowance = _MAX_UINT256; - - } else if (assetProxyId == IAssetData(address(0)).ERC20Bridge.selector) { - // Get address of ERC20 token and bridge contract - (, address tokenAddress, address bridgeAddress,) = decodeERC20BridgeAssetData(assetData); - if (tokenAddress == _getDaiAddress() && bridgeAddress == _CHAI_BRIDGE_ADDRESS) { - bytes memory allowanceData = abi.encodeWithSelector( - IERC20Token(address(0)).allowance.selector, - ownerAddress, - _CHAI_BRIDGE_ADDRESS - ); - (bool success, bytes memory returnData) = _getChaiAddress().staticcall(allowanceData); - uint256 chaiAllowance = success && returnData.length == 32 ? returnData.readUint256(0) : 0; - // Dai allowance is unlimited if Chai allowance is unlimited - allowance = chaiAllowance == _MAX_UINT256 ? _MAX_UINT256 : _convertChaiToDaiAmount(chaiAllowance); - } - // Allowance will be 0 if bridge is not supported - } - - // Allowance will be 0 if the assetProxyId is unknown - return allowance; - } - - /// @dev Calls getAssetProxyAllowance() for each element of assetData. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. - /// @return An array of asset allowances from getAllowance(), with each - /// element corresponding to the same-indexed element in the assetData input. - function getBatchAssetProxyAllowances(address ownerAddress, bytes[] memory assetData) - public - returns (uint256[] memory allowances) - { - uint256 length = assetData.length; - allowances = new uint256[](length); - for (uint256 i = 0; i != length; i++) { - allowances[i] = getAssetProxyAllowance(ownerAddress, assetData[i]); - } - return allowances; - } - - /// @dev Calls getBalance() and getAllowance() for assetData. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Details of asset, encoded per the AssetProxy contract specification. - /// @return Number of assets (or asset baskets) held by owner, and number - /// of assets (or asset baskets) that the corresponding AssetProxy is authorized to spend. - function getBalanceAndAssetProxyAllowance(address ownerAddress, bytes memory assetData) - public - returns (uint256 balance, uint256 allowance) - { - balance = getBalance(ownerAddress, assetData); - allowance = getAssetProxyAllowance(ownerAddress, assetData); - return (balance, allowance); - } - - /// @dev Calls getBatchBalances() and getBatchAllowances() for each element of assetData. - /// @param ownerAddress Owner of the assets specified by assetData. - /// @param assetData Array of asset details, each encoded per the AssetProxy contract specification. - /// @return An array of asset balances from getBalance(), and an array of - /// asset allowances from getAllowance(), with each element - /// corresponding to the same-indexed element in the assetData input. - function getBatchBalancesAndAssetProxyAllowances(address ownerAddress, bytes[] memory assetData) - public - returns (uint256[] memory balances, uint256[] memory allowances) - { - balances = getBatchBalances(ownerAddress, assetData); - allowances = getBatchAssetProxyAllowances(ownerAddress, assetData); - return (balances, allowances); - } - /// @dev Decode AssetProxy identifier /// @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC-721, ERC1155, or MultiAsset asset. /// @return The AssetProxy identifier @@ -691,44 +351,4 @@ contract LibAssetData is revert("WRONG_PROXY_ID"); } } - - /// @dev Queries balance of an ERC20 token. Returns 0 if call was unsuccessful. - /// @param tokenAddress Address of ERC20 token. - /// @param ownerAddress Address of owner of ERC20 token. - /// @return balance ERC20 token balance of owner. - function _erc20BalanceOf( - address tokenAddress, - address ownerAddress - ) - internal - view - returns (uint256 balance) - { - // Encode data for `balanceOf(ownerAddress)` - bytes memory balanceOfData = abi.encodeWithSelector( - IERC20Token(address(0)).balanceOf.selector, - ownerAddress - ); - - // Query balance - (bool success, bytes memory returnData) = tokenAddress.staticcall(balanceOfData); - balance = success && returnData.length == 32 ? returnData.readUint256(0) : 0; - return balance; - } - - /// @dev Converts an amount of Chai into its equivalent Dai amount. - /// Also accumulates Dai from DSR if called after the last time it was collected. - /// @param chaiAmount Amount of Chai to converts. - function _convertChaiToDaiAmount(uint256 chaiAmount) - internal - returns (uint256 daiAmount) - { - PotLike pot = IChai(_getChaiAddress()).pot(); - // Accumulate savings if called after last time savings were collected - uint256 chiMultiplier = (now > pot.rho()) - ? pot.drip() - : pot.chi(); - daiAmount = LibMath.getPartialAmountFloor(chiMultiplier, 10**27, chaiAmount); - return daiAmount; - } } diff --git a/contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol b/contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol new file mode 100644 index 0000000000..7dbe548211 --- /dev/null +++ b/contracts/dev-utils/contracts/src/LibOrderTransferSimulation.sol @@ -0,0 +1,227 @@ +/* + + 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.16; +pragma experimental ABIEncoderV2; + + +import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; +import "@0x/contracts-exchange/contracts/src/libs/LibExchangeRichErrorDecoder.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibExchangeRichErrors.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; +import "@0x/contracts-exchange-libs/contracts/src/LibFillResults.sol"; +import "@0x/contracts-utils/contracts/src/LibBytes.sol"; + + +library LibOrderTransferSimulation { + using LibBytes for bytes; + + enum OrderTransferResults { + TakerAssetDataFailed, // Transfer of takerAsset failed + MakerAssetDataFailed, // Transfer of makerAsset failed + TakerFeeAssetDataFailed, // Transfer of takerFeeAsset failed + MakerFeeAssetDataFailed, // Transfer of makerFeeAsset failed + TransfersSuccessful // All transfers in the order were successful + } + + // NOTE(jalextowle): This is a random address that we use to avoid issues that addresses like `address(1)` + // may cause later. + address constant internal UNUSED_ADDRESS = address(0x377f698C4c287018D09b516F415317aEC5919332); + + // keccak256(abi.encodeWithSignature("Error(string)", "TRANSFERS_SUCCESSFUL")); + bytes32 constant internal _TRANSFERS_SUCCESSFUL_RESULT_HASH = 0xf43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce0; + + /// @dev Simulates the maker transfers within an order and returns the index of the first failed transfer. + /// @param order The order to simulate transfers for. + /// @param takerAddress The address of the taker that will fill the order. + /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill. + /// @return The index of the first failed transfer (or 4 if all transfers are successful). + function getSimulatedOrderMakerTransferResults( + address exchange, + LibOrder.Order memory order, + address takerAddress, + uint256 takerAssetFillAmount + ) + public + returns (OrderTransferResults orderTransferResults) + { + LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResults( + order, + takerAssetFillAmount, + IExchange(exchange).protocolFeeMultiplier(), + tx.gasprice + ); + + bytes[] memory assetData = new bytes[](2); + address[] memory fromAddresses = new address[](2); + address[] memory toAddresses = new address[](2); + uint256[] memory amounts = new uint256[](2); + + // Transfer `makerAsset` from maker to taker + assetData[0] = order.makerAssetData; + fromAddresses[0] = order.makerAddress; + toAddresses[0] = takerAddress == address(0) ? UNUSED_ADDRESS : takerAddress; + amounts[0] = fillResults.makerAssetFilledAmount; + + // Transfer `makerFeeAsset` from maker to feeRecipient + assetData[1] = order.makerFeeAssetData; + fromAddresses[1] = order.makerAddress; + toAddresses[1] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress; + amounts[1] = fillResults.makerFeePaid; + + return _simulateTransferFromCalls( + exchange, + assetData, + fromAddresses, + toAddresses, + amounts + ); + } + + /// @dev Simulates all of the transfers within an order and returns the index of the first failed transfer. + /// @param order The order to simulate transfers for. + /// @param takerAddress The address of the taker that will fill the order. + /// @param takerAssetFillAmount The amount of takerAsset that the taker wished to fill. + /// @return The index of the first failed transfer (or 4 if all transfers are successful). + function getSimulatedOrderTransferResults( + address exchange, + LibOrder.Order memory order, + address takerAddress, + uint256 takerAssetFillAmount + ) + public + returns (OrderTransferResults orderTransferResults) + { + LibFillResults.FillResults memory fillResults = LibFillResults.calculateFillResults( + order, + takerAssetFillAmount, + IExchange(exchange).protocolFeeMultiplier(), + tx.gasprice + ); + + // Create input arrays + bytes[] memory assetData = new bytes[](4); + address[] memory fromAddresses = new address[](4); + address[] memory toAddresses = new address[](4); + uint256[] memory amounts = new uint256[](4); + + // Transfer `takerAsset` from taker to maker + assetData[0] = order.takerAssetData; + fromAddresses[0] = takerAddress; + toAddresses[0] = order.makerAddress; + amounts[0] = takerAssetFillAmount; + + // Transfer `makerAsset` from maker to taker + assetData[1] = order.makerAssetData; + fromAddresses[1] = order.makerAddress; + toAddresses[1] = takerAddress == address(0) ? UNUSED_ADDRESS : takerAddress; + amounts[1] = fillResults.makerAssetFilledAmount; + + // Transfer `takerFeeAsset` from taker to feeRecipient + assetData[2] = order.takerFeeAssetData; + fromAddresses[2] = takerAddress; + toAddresses[2] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress; + amounts[2] = fillResults.takerFeePaid; + + // Transfer `makerFeeAsset` from maker to feeRecipient + assetData[3] = order.makerFeeAssetData; + fromAddresses[3] = order.makerAddress; + toAddresses[3] = order.feeRecipientAddress == address(0) ? UNUSED_ADDRESS : order.feeRecipientAddress; + amounts[3] = fillResults.makerFeePaid; + + return _simulateTransferFromCalls( + exchange, + assetData, + fromAddresses, + toAddresses, + amounts + ); + } + + /// @dev Simulates all of the transfers for each given order and returns the indices of each first failed transfer. + /// @param orders Array of orders to individually simulate transfers for. + /// @param takerAddresses Array of addresses of takers that will fill each order. + /// @param takerAssetFillAmounts Array of amounts of takerAsset that will be filled for each order. + /// @return The indices of the first failed transfer (or 4 if all transfers are successful) for each order. + function getSimulatedOrdersTransferResults( + address exchange, + LibOrder.Order[] memory orders, + address[] memory takerAddresses, + uint256[] memory takerAssetFillAmounts + ) + public + returns (OrderTransferResults[] memory orderTransferResults) + { + uint256 length = orders.length; + orderTransferResults = new OrderTransferResults[](length); + for (uint256 i = 0; i != length; i++) { + orderTransferResults[i] = getSimulatedOrderTransferResults( + exchange, + orders[i], + takerAddresses[i], + takerAssetFillAmounts[i] + ); + } + return orderTransferResults; + } + + /// @dev Makes the simulation call with information about the transfers and processes + /// the returndata. + /// @param assetData The assetdata to use to make transfers. + /// @param fromAddresses The addresses to transfer funds. + /// @param toAddresses The addresses that will receive funds + /// @param amounts The amounts involved in the transfer. + function _simulateTransferFromCalls( + address exchange, + bytes[] memory assetData, + address[] memory fromAddresses, + address[] memory toAddresses, + uint256[] memory amounts + ) + private + returns (OrderTransferResults orderTransferResults) + { + // Encode data for `simulateDispatchTransferFromCalls(assetData, fromAddresses, toAddresses, amounts)` + bytes memory simulateDispatchTransferFromCallsData = abi.encodeWithSelector( + IExchange(address(0)).simulateDispatchTransferFromCalls.selector, + assetData, + fromAddresses, + toAddresses, + amounts + ); + + // Perform call and catch revert + (, bytes memory returnData) = address(exchange).call(simulateDispatchTransferFromCallsData); + + bytes4 selector = returnData.readBytes4(0); + if (selector == LibExchangeRichErrors.AssetProxyDispatchErrorSelector()) { + // Decode AssetProxyDispatchError and return index of failed transfer + (, bytes32 failedTransferIndex,) = LibExchangeRichErrorDecoder.decodeAssetProxyDispatchError(returnData); + return OrderTransferResults(uint8(uint256(failedTransferIndex))); + } else if (selector == LibExchangeRichErrors.AssetProxyTransferErrorSelector()) { + // Decode AssetProxyTransferError and return index of failed transfer + (bytes32 failedTransferIndex, ,) = LibExchangeRichErrorDecoder.decodeAssetProxyTransferError(returnData); + return OrderTransferResults(uint8(uint256(failedTransferIndex))); + } else if (keccak256(returnData) == _TRANSFERS_SUCCESSFUL_RESULT_HASH) { + // All transfers were successful + return OrderTransferResults.TransfersSuccessful; + } else { + revert("UNKNOWN_RETURN_DATA"); + } + } +} diff --git a/contracts/dev-utils/contracts/src/LibTransactionDecoder.sol b/contracts/dev-utils/contracts/src/LibTransactionDecoder.sol index 476cf1c4c5..34df3cdebc 100644 --- a/contracts/dev-utils/contracts/src/LibTransactionDecoder.sol +++ b/contracts/dev-utils/contracts/src/LibTransactionDecoder.sol @@ -16,7 +16,7 @@ */ -pragma solidity ^0.5.5; +pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; @@ -24,7 +24,7 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; -contract LibTransactionDecoder { +library LibTransactionDecoder { using LibBytes for bytes; diff --git a/contracts/dev-utils/contracts/src/OrderValidationUtils.sol b/contracts/dev-utils/contracts/src/OrderValidationUtils.sol index 0ed383f779..c7435165dd 100644 --- a/contracts/dev-utils/contracts/src/OrderValidationUtils.sol +++ b/contracts/dev-utils/contracts/src/OrderValidationUtils.sol @@ -16,36 +16,26 @@ */ -pragma solidity ^0.5.9; +pragma solidity ^0.5.16; pragma experimental ABIEncoderV2; -import "@0x/contracts-exchange/contracts/src/interfaces/IExchange.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; import "@0x/contracts-exchange-libs/contracts/src/LibMath.sol"; import "@0x/contracts-utils/contracts/src/LibBytes.sol"; import "@0x/contracts-utils/contracts/src/LibSafeMath.sol"; +import "./Addresses.sol"; +import "./AssetBalance.sol"; import "./LibAssetData.sol"; -import "./OrderTransferSimulationUtils.sol"; +import "./LibOrderTransferSimulation.sol"; contract OrderValidationUtils is - LibAssetData, - OrderTransferSimulationUtils + Addresses, + AssetBalance { using LibBytes for bytes; using LibSafeMath for uint256; - constructor ( - address _exchange, - address _chaiBridge - ) - public - LibAssetData( - _exchange, - _chaiBridge - ) - {} - /// @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. @@ -65,23 +55,22 @@ contract OrderValidationUtils is ) { // Get info specific to order - orderInfo = _EXCHANGE.getOrderInfo(order); + orderInfo = IExchange(exchangeAddress).getOrderInfo(order); // Validate the maker's signature address makerAddress = order.makerAddress; - isValidSignature = _EXCHANGE.isValidOrderSignature( + isValidSignature = IExchange(exchangeAddress).isValidOrderSignature( order, signature ); // Get the transferable amount of the `makerAsset` - uint256 transferableMakerAssetAmount = getTransferableAssetAmount(makerAddress, order.makerAssetData); - - // Assign to stack variables to reduce redundant mloads/sloads - uint256 takerAssetAmount = order.takerAssetAmount; - uint256 makerFee = order.makerFee; + uint256 transferableMakerAssetAmount = _getTransferableConvertedMakerAssetAmount( + order + ); - // Get the amount of `takerAsset` that is transferable to maker given the transferability of `makerAsset`, `makerFeeAsset`, + // Get the amount of `takerAsset` that is transferable to maker given the + // transferability of `makerAsset`, `makerFeeAsset`, // and the total amounts specified in the order uint256 transferableTakerAssetAmount; if (order.makerAssetData.equals(order.makerFeeAssetData)) { @@ -89,32 +78,35 @@ contract OrderValidationUtils is // transferableMakerAssetAmount / (makerAssetAmount + makerFee) transferableTakerAssetAmount = LibMath.getPartialAmountFloor( transferableMakerAssetAmount, - order.makerAssetAmount.safeAdd(makerFee), - takerAssetAmount + order.makerAssetAmount.safeAdd(order.makerFee), + order.takerAssetAmount ); } else { // If `makerFee` is 0, the % that can be filled is (transferableMakerAssetAmount / makerAssetAmount) - if (makerFee == 0) { + if (order.makerFee == 0) { transferableTakerAssetAmount = LibMath.getPartialAmountFloor( transferableMakerAssetAmount, order.makerAssetAmount, - takerAssetAmount + order.takerAssetAmount ); // If `makerAsset` does not equal `makerFeeAsset`, the % that can be filled is the lower of // (transferableMakerAssetAmount / makerAssetAmount) and (transferableMakerAssetFeeAmount / makerFee) } else { // Get the transferable amount of the `makerFeeAsset` - uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount(makerAddress, order.makerFeeAssetData); + uint256 transferableMakerFeeAssetAmount = getTransferableAssetAmount( + makerAddress, + order.makerFeeAssetData + ); uint256 transferableMakerToTakerAmount = LibMath.getPartialAmountFloor( transferableMakerAssetAmount, order.makerAssetAmount, - takerAssetAmount + order.takerAssetAmount ); uint256 transferableMakerFeeToTakerAmount = LibMath.getPartialAmountFloor( transferableMakerFeeAssetAmount, - makerFee, - takerAssetAmount + order.makerFee, + order.takerAssetAmount ); transferableTakerAssetAmount = LibSafeMath.min256(transferableMakerToTakerAmount, transferableMakerFeeToTakerAmount); } @@ -122,16 +114,17 @@ contract OrderValidationUtils is // `fillableTakerAssetAmount` is the lower of the order's remaining `takerAssetAmount` and the `transferableTakerAssetAmount` fillableTakerAssetAmount = LibSafeMath.min256( - takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount), + order.takerAssetAmount.safeSub(orderInfo.orderTakerAssetFilledAmount), transferableTakerAssetAmount ); // Execute the maker transfers. - fillableTakerAssetAmount = getSimulatedOrderMakerTransferResults( + fillableTakerAssetAmount = LibOrderTransferSimulation.getSimulatedOrderMakerTransferResults( + exchangeAddress, order, order.takerAddress, fillableTakerAssetAmount - ) == OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0; + ) == LibOrderTransferSimulation.OrderTransferResults.TransfersSuccessful ? fillableTakerAssetAmount : 0; if (!_isAssetDataValid(order.takerAssetData)) { fillableTakerAssetAmount = 0; @@ -181,7 +174,7 @@ contract OrderValidationUtils is return (ordersInfo, fillableTakerAssetAmounts, isValidSignature); } - /// @dev Gets the amount of an asset transferable by the owner. + /// @dev Gets the amount of an asset transferable by the maker of an order. /// @param ownerAddress Address of the owner of the asset. /// @param assetData Description of tokens, per the AssetProxy contract specification. /// @return The amount of the asset tranferable by the owner. @@ -193,7 +186,26 @@ contract OrderValidationUtils is public returns (uint256 transferableAssetAmount) { - (uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance(ownerAddress, assetData); + (uint256 balance, uint256 allowance) = getBalanceAndAssetProxyAllowance( + ownerAddress, + assetData + ); + transferableAssetAmount = LibSafeMath.min256(balance, allowance); + return transferableAssetAmount; + } + + /// @dev Gets the amount of an asset transferable by the maker of an order. + /// Similar to `getTransferableAssetAmount()`, but can handle maker asset + /// types that depend on taker assets being transferred first (e.g., Dydx bridge). + /// @param order The order. + /// @return transferableAssetAmount Amount of maker asset that can be transferred. + function _getTransferableConvertedMakerAssetAmount( + LibOrder.Order memory order + ) + internal + returns (uint256 transferableAssetAmount) + { + (uint256 balance, uint256 allowance) = _getConvertibleMakerBalanceAndAssetProxyAllowance(order); transferableAssetAmount = LibSafeMath.min256(balance, allowance); return transferableAssetAmount; } @@ -221,7 +233,8 @@ contract OrderValidationUtils is } // Get array of values and array of assetDatas - (, uint256[] memory assetAmounts, bytes[] memory nestedAssetData) = decodeMultiAssetData(assetData); + (, , bytes[] memory nestedAssetData) = + LibAssetData.decodeMultiAssetData(assetData); uint256 length = nestedAssetData.length; for (uint256 i = 0; i != length; i++) { diff --git a/contracts/dev-utils/package.json b/contracts/dev-utils/package.json index 0e876a5823..026325881e 100644 --- a/contracts/dev-utils/package.json +++ b/contracts/dev-utils/package.json @@ -8,7 +8,7 @@ "main": "lib/src/index.js", "scripts": { "build": "yarn pre_build && tsc -b", - "test": "yarn assert_deployable && echo !!! Tests are run via @0x/contracts-integrations !!!", + "test": "yarn assert_deployable", "assert_deployable": "node -e \"const bytecodeLen = (require('./generated-artifacts/DevUtils.json').compilerOutput.evm.bytecode.object.length-2)/2; assert(bytecodeLen<=0x6000,'DevUtils contract is too big to deploy, per EIP-170. '+bytecodeLen+'>'+0x6000)\"", "build:ci": "yarn build", "pre_build": "run-s compile quantify_bytecode contracts:gen generate_contract_wrappers contracts:copy", @@ -27,8 +27,8 @@ "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES" }, "config": { - "publicInterfaceContracts": "DevUtils,LibAssetData,LibTransactionDecoder", - "abis": "./test/generated-artifacts/@(DevUtils|EthBalanceChecker|LibAssetData|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json", + "publicInterfaceContracts": "DevUtils,LibAssetData,LibOrderTransferSimulation,LibTransactionDecoder", + "abis": "./test/generated-artifacts/@(Addresses|AssetBalance|DevUtils|EthBalanceChecker|ExternalFunctions|LibAssetData|LibOrderTransferSimulation|LibTransactionDecoder|OrderTransferSimulationUtils|OrderValidationUtils).json", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually." }, "repository": { @@ -41,12 +41,17 @@ }, "homepage": "https://github.com/0xProject/0x-monorepo/contracts/dev-utils/README.md", "devDependencies": { + "@0x/contracts-asset-proxy": "^3.1.1", + "@0x/contracts-erc20": "^3.0.4", + "@0x/contracts-test-utils": "^5.1.1", + "@0x/types": "^3.1.1", "@0x/abi-gen": "^5.1.0", "@0x/assert": "^3.0.4", "@0x/contracts-gen": "^2.0.4", "@0x/sol-compiler": "^4.0.4", "@0x/ts-doc-gen": "^0.0.22", "@0x/tslint-config": "^4.0.0", + "@0x/utils": "^5.2.0", "@types/node": "*", "ethereum-types": "^3.0.0", "ethers": "~4.0.4", diff --git a/contracts/dev-utils/src/artifacts.ts b/contracts/dev-utils/src/artifacts.ts index 3c2f022c66..37178cef1e 100644 --- a/contracts/dev-utils/src/artifacts.ts +++ b/contracts/dev-utils/src/artifacts.ts @@ -7,9 +7,11 @@ import { ContractArtifact } from 'ethereum-types'; import * as DevUtils from '../generated-artifacts/DevUtils.json'; import * as LibAssetData from '../generated-artifacts/LibAssetData.json'; +import * as LibOrderTransferSimulation from '../generated-artifacts/LibOrderTransferSimulation.json'; import * as LibTransactionDecoder from '../generated-artifacts/LibTransactionDecoder.json'; export const artifacts = { DevUtils: DevUtils as ContractArtifact, LibAssetData: LibAssetData as ContractArtifact, + LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact, LibTransactionDecoder: LibTransactionDecoder as ContractArtifact, }; diff --git a/contracts/dev-utils/src/index.ts b/contracts/dev-utils/src/index.ts index 86d122eb2e..91a089b69a 100644 --- a/contracts/dev-utils/src/index.ts +++ b/contracts/dev-utils/src/index.ts @@ -1,5 +1,5 @@ export { artifacts } from './artifacts'; -export { DevUtilsContract, LibAssetDataContract, LibTransactionDecoderContract } from './wrappers'; +export { DevUtilsContract } from './wrappers'; export { ContractArtifact, ContractChains, diff --git a/contracts/dev-utils/src/wrappers.ts b/contracts/dev-utils/src/wrappers.ts index e07c65436d..c00882a21a 100644 --- a/contracts/dev-utils/src/wrappers.ts +++ b/contracts/dev-utils/src/wrappers.ts @@ -5,4 +5,5 @@ */ export * from '../generated-wrappers/dev_utils'; export * from '../generated-wrappers/lib_asset_data'; +export * from '../generated-wrappers/lib_order_transfer_simulation'; export * from '../generated-wrappers/lib_transaction_decoder'; diff --git a/contracts/dev-utils/test/artifacts.ts b/contracts/dev-utils/test/artifacts.ts index 767d984040..7a57acf66b 100644 --- a/contracts/dev-utils/test/artifacts.ts +++ b/contracts/dev-utils/test/artifacts.ts @@ -5,16 +5,24 @@ */ import { ContractArtifact } from 'ethereum-types'; +import * as Addresses from '../test/generated-artifacts/Addresses.json'; +import * as AssetBalance from '../test/generated-artifacts/AssetBalance.json'; import * as DevUtils from '../test/generated-artifacts/DevUtils.json'; import * as EthBalanceChecker from '../test/generated-artifacts/EthBalanceChecker.json'; +import * as ExternalFunctions from '../test/generated-artifacts/ExternalFunctions.json'; import * as LibAssetData from '../test/generated-artifacts/LibAssetData.json'; +import * as LibOrderTransferSimulation from '../test/generated-artifacts/LibOrderTransferSimulation.json'; import * as LibTransactionDecoder from '../test/generated-artifacts/LibTransactionDecoder.json'; import * as OrderTransferSimulationUtils from '../test/generated-artifacts/OrderTransferSimulationUtils.json'; import * as OrderValidationUtils from '../test/generated-artifacts/OrderValidationUtils.json'; export const artifacts = { + Addresses: Addresses as ContractArtifact, + AssetBalance: AssetBalance as ContractArtifact, DevUtils: DevUtils as ContractArtifact, EthBalanceChecker: EthBalanceChecker as ContractArtifact, + ExternalFunctions: ExternalFunctions as ContractArtifact, LibAssetData: LibAssetData as ContractArtifact, + LibOrderTransferSimulation: LibOrderTransferSimulation as ContractArtifact, LibTransactionDecoder: LibTransactionDecoder as ContractArtifact, OrderTransferSimulationUtils: OrderTransferSimulationUtils as ContractArtifact, OrderValidationUtils: OrderValidationUtils as ContractArtifact, diff --git a/contracts/dev-utils/test/wrappers.ts b/contracts/dev-utils/test/wrappers.ts index cbbea9c7cc..0760a7390d 100644 --- a/contracts/dev-utils/test/wrappers.ts +++ b/contracts/dev-utils/test/wrappers.ts @@ -3,9 +3,13 @@ * Warning: This file is auto-generated by contracts-gen. Don't edit manually. * ----------------------------------------------------------------------------- */ +export * from '../test/generated-wrappers/addresses'; +export * from '../test/generated-wrappers/asset_balance'; export * from '../test/generated-wrappers/dev_utils'; export * from '../test/generated-wrappers/eth_balance_checker'; +export * from '../test/generated-wrappers/external_functions'; export * from '../test/generated-wrappers/lib_asset_data'; +export * from '../test/generated-wrappers/lib_order_transfer_simulation'; export * from '../test/generated-wrappers/lib_transaction_decoder'; export * from '../test/generated-wrappers/order_transfer_simulation_utils'; export * from '../test/generated-wrappers/order_validation_utils'; diff --git a/contracts/dev-utils/tsconfig.json b/contracts/dev-utils/tsconfig.json index ec5f1f9157..9c2a01383f 100644 --- a/contracts/dev-utils/tsconfig.json +++ b/contracts/dev-utils/tsconfig.json @@ -5,10 +5,15 @@ "files": [ "generated-artifacts/DevUtils.json", "generated-artifacts/LibAssetData.json", + "generated-artifacts/LibOrderTransferSimulation.json", "generated-artifacts/LibTransactionDecoder.json", + "test/generated-artifacts/Addresses.json", + "test/generated-artifacts/AssetBalance.json", "test/generated-artifacts/DevUtils.json", "test/generated-artifacts/EthBalanceChecker.json", + "test/generated-artifacts/ExternalFunctions.json", "test/generated-artifacts/LibAssetData.json", + "test/generated-artifacts/LibOrderTransferSimulation.json", "test/generated-artifacts/LibTransactionDecoder.json", "test/generated-artifacts/OrderTransferSimulationUtils.json", "test/generated-artifacts/OrderValidationUtils.json" diff --git a/contracts/erc20/CHANGELOG.json b/contracts/erc20/CHANGELOG.json index 3eea026c86..8c40a31f94 100644 --- a/contracts/erc20/CHANGELOG.json +++ b/contracts/erc20/CHANGELOG.json @@ -4,11 +4,11 @@ "changes": [ { "note": "Add `allowance()` and `balanceOf()` to `LibERC20Token`", - "pr": 2462 + "pr": 2464 }, { "note": "Fix broken tests", - "pr": 2462 + "pr": 2456 } ] }, diff --git a/contracts/erc20/contracts/src/LibERC20Token.sol b/contracts/erc20/contracts/src/LibERC20Token.sol index 830ef11f8f..2ba86732b3 100644 --- a/contracts/erc20/contracts/src/LibERC20Token.sol +++ b/contracts/erc20/contracts/src/LibERC20Token.sol @@ -94,7 +94,8 @@ library LibERC20Token { /// @dev Retrieves the number of decimals for a token. /// Returns `18` if the call reverts. - /// @return The number of decimals places for the token. + /// @param token The address of the token contract. + /// @return tokenDecimals The number of decimals places for the token. function decimals(address token) internal view @@ -107,6 +108,50 @@ library LibERC20Token { } } + /// @dev Retrieves the allowance for a token, owner, and spender. + /// Returns `0` if the call reverts. + /// @param token The address of the token contract. + /// @param owner The owner of the tokens. + /// @param spender The address the spender. + /// @return allowance The allowance for a token, owner, and spender. + function allowance(address token, address owner, address spender) + internal + view + returns (uint256 allowance_) + { + (bool didSucceed, bytes memory resultData) = token.staticcall( + abi.encodeWithSelector( + IERC20Token(0).allowance.selector, + owner, + spender + ) + ); + if (didSucceed && resultData.length == 32) { + allowance_ = LibBytes.readUint256(resultData, 0); + } + } + + /// @dev Retrieves the balance for a token owner. + /// Returns `0` if the call reverts. + /// @param token The address of the token contract. + /// @param owner The owner of the tokens. + /// @return balance The token balance of an owner. + function balanceOf(address token, address owner) + internal + view + returns (uint256 balance) + { + (bool didSucceed, bytes memory resultData) = token.staticcall( + abi.encodeWithSelector( + IERC20Token(0).balanceOf.selector, + owner + ) + ); + if (didSucceed && resultData.length == 32) { + balance = LibBytes.readUint256(resultData, 0); + } + } + /// @dev Executes a call on address `target` with calldata `callData` /// and asserts that either nothing was returned or a single boolean /// was returned equal to `true`. diff --git a/contracts/integrations/CHANGELOG.json b/contracts/integrations/CHANGELOG.json index 432d0ef9e7..7553bae159 100644 --- a/contracts/integrations/CHANGELOG.json +++ b/contracts/integrations/CHANGELOG.json @@ -5,6 +5,10 @@ { "note": "Remove dependency on `DevUtils` for asset data encoding/decoding", "pr": 2462 + }, + { + "note": "Update tests for refactored `DevUtils`", + "pr": 2464 } ] }, diff --git a/contracts/integrations/test/dev-utils/dev_utils_mainnet_test.ts b/contracts/integrations/test/dev-utils/dev_utils_mainnet_test.ts index b042ed628f..1aa36ff346 100644 --- a/contracts/integrations/test/dev-utils/dev_utils_mainnet_test.ts +++ b/contracts/integrations/test/dev-utils/dev_utils_mainnet_test.ts @@ -26,8 +26,9 @@ blockchainTests.fork.resets('DevUtils mainnet tests', env => { before(async () => { [noDaiAddress] = await env.getAccountAddressesAsync(); - devUtils = await DevUtilsContract.deployFrom0xArtifactAsync( + devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( devUtilsArtifacts.DevUtils, + devUtilsArtifacts, env.provider, env.txDefaults, devUtilsArtifacts, diff --git a/contracts/integrations/test/dev-utils/get_order_hash.ts b/contracts/integrations/test/dev-utils/get_order_hash.ts index bfa31dc6c1..862b9a188b 100644 --- a/contracts/integrations/test/dev-utils/get_order_hash.ts +++ b/contracts/integrations/test/dev-utils/get_order_hash.ts @@ -19,8 +19,9 @@ blockchainTests('DevUtils.getOrderHash', env => { exchangeArtifacts, new BigNumber(chainId), ); - devUtils = await DevUtilsContract.deployFrom0xArtifactAsync( + devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( artifacts.DevUtils, + artifacts, env.provider, env.txDefaults, artifacts, diff --git a/contracts/integrations/test/dev-utils/lib_asset_data.ts b/contracts/integrations/test/dev-utils/lib_asset_data.ts index 442e31ee9f..7594a44f11 100644 --- a/contracts/integrations/test/dev-utils/lib_asset_data.ts +++ b/contracts/integrations/test/dev-utils/lib_asset_data.ts @@ -1,13 +1,13 @@ import * as crypto from 'crypto'; import { artifacts as proxyArtifacts, TestStaticCallTargetContract } from '@0x/contracts-asset-proxy'; -import { artifacts, LibAssetDataContract } from '@0x/contracts-dev-utils'; +import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils'; import { ERC1155MintableContract } from '@0x/contracts-erc1155'; import { DummyERC20TokenContract } from '@0x/contracts-erc20'; import { DummyERC721TokenContract } from '@0x/contracts-erc721'; import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; import { AssetProxyId } from '@0x/types'; -import { BigNumber, hexUtils, LibBytesRevertErrors, StringRevertError } from '@0x/utils'; +import { BigNumber, hexUtils, LibBytesRevertErrors } from '@0x/utils'; import { Actor } from '../framework/actors/base'; import { DeploymentManager } from '../framework/deployment_manager'; @@ -53,7 +53,7 @@ const KNOWN_STATIC_CALL_ENCODING = { blockchainTests.resets('LibAssetData', env => { let deployment: DeploymentManager; let staticCallTarget: TestStaticCallTargetContract; - let libAssetData: LibAssetDataContract; + let devUtils: DevUtilsContract; let tokenOwner: Actor; @@ -73,8 +73,9 @@ blockchainTests.resets('LibAssetData', env => { }); tokenOwner = new Actor({ name: 'Token Owner', deployment }); - libAssetData = await LibAssetDataContract.deployFrom0xArtifactAsync( - artifacts.LibAssetData, + devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( + artifacts.DevUtils, + artifacts, env.provider, env.txDefaults, artifacts, @@ -104,7 +105,7 @@ blockchainTests.resets('LibAssetData', env => { }); it('should have a deployed-to address', () => { - expect(libAssetData.address.slice(0, 2)).to.equal('0x'); + expect(devUtils.address.slice(0, 2)).to.equal('0x'); }); describe('encoding and decoding', () => { @@ -117,17 +118,17 @@ blockchainTests.resets('LibAssetData', env => { ]; for (const [assetData, proxyId] of assetDataScenarios) { - expect(await libAssetData.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId); + expect(await devUtils.decodeAssetProxyId(assetData).callAsync()).to.equal(proxyId); } }); it('should encode ERC20 asset data', async () => { - expect(await libAssetData.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal( + expect(await devUtils.encodeERC20AssetData(KNOWN_ERC20_ENCODING.address).callAsync()).to.equal( KNOWN_ERC20_ENCODING.assetData, ); }); it('should decode ERC20 asset data', async () => { - expect(await libAssetData.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([ + expect(await devUtils.decodeERC20AssetData(KNOWN_ERC20_ENCODING.assetData).callAsync()).to.deep.equal([ AssetProxyId.ERC20, KNOWN_ERC20_ENCODING.address, ]); @@ -135,21 +136,23 @@ blockchainTests.resets('LibAssetData', env => { it('should encode ERC721 asset data', async () => { expect( - await libAssetData + await devUtils .encodeERC721AssetData(KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId) .callAsync(), ).to.equal(KNOWN_ERC721_ENCODING.assetData); }); it('should decode ERC721 asset data', async () => { - expect(await libAssetData.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal( - [AssetProxyId.ERC721, KNOWN_ERC721_ENCODING.address, KNOWN_ERC721_ENCODING.tokenId], - ); + expect(await devUtils.decodeERC721AssetData(KNOWN_ERC721_ENCODING.assetData).callAsync()).to.deep.equal([ + AssetProxyId.ERC721, + KNOWN_ERC721_ENCODING.address, + KNOWN_ERC721_ENCODING.tokenId, + ]); }); it('should encode ERC1155 asset data', async () => { expect( - await libAssetData + await devUtils .encodeERC1155AssetData( KNOWN_ERC1155_ENCODING.tokenAddress, KNOWN_ERC1155_ENCODING.tokenIds, @@ -161,9 +164,7 @@ blockchainTests.resets('LibAssetData', env => { }); it('should decode ERC1155 asset data', async () => { - expect( - await libAssetData.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync(), - ).to.deep.equal([ + expect(await devUtils.decodeERC1155AssetData(KNOWN_ERC1155_ENCODING.assetData).callAsync()).to.deep.equal([ AssetProxyId.ERC1155, KNOWN_ERC1155_ENCODING.tokenAddress, KNOWN_ERC1155_ENCODING.tokenIds, @@ -174,7 +175,7 @@ blockchainTests.resets('LibAssetData', env => { it('should encode multiasset data', async () => { expect( - await libAssetData + await devUtils .encodeMultiAssetData( KNOWN_MULTI_ASSET_ENCODING.amounts, KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, @@ -184,18 +185,18 @@ blockchainTests.resets('LibAssetData', env => { }); it('should decode multiasset data', async () => { - expect( - await libAssetData.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync(), - ).to.deep.equal([ - AssetProxyId.MultiAsset, - KNOWN_MULTI_ASSET_ENCODING.amounts, - KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, - ]); + expect(await devUtils.decodeMultiAssetData(KNOWN_MULTI_ASSET_ENCODING.assetData).callAsync()).to.deep.equal( + [ + AssetProxyId.MultiAsset, + KNOWN_MULTI_ASSET_ENCODING.amounts, + KNOWN_MULTI_ASSET_ENCODING.nestedAssetData, + ], + ); }); it('should encode StaticCall data', async () => { expect( - await libAssetData + await devUtils .encodeStaticCallAssetData( KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress, KNOWN_STATIC_CALL_ENCODING.staticCallData, @@ -207,7 +208,7 @@ blockchainTests.resets('LibAssetData', env => { it('should decode StaticCall data', async () => { expect( - await libAssetData.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(), + await devUtils.decodeStaticCallAssetData(KNOWN_STATIC_CALL_ENCODING.assetData).callAsync(), ).to.deep.equal([ AssetProxyId.StaticCall, KNOWN_STATIC_CALL_ENCODING.staticCallTargetAddress, @@ -227,16 +228,14 @@ blockchainTests.resets('LibAssetData', env => { ]; for (const data of assetData) { - await libAssetData.revertIfInvalidAssetData(data).callAsync(); + await devUtils.revertIfInvalidAssetData(data).callAsync(); } return; }); it('should revert for invalid assetProxyId', async () => { const badAssetData = `0x${crypto.randomBytes(4).toString('hex')}${constants.NULL_ADDRESS}`; - await expect(libAssetData.revertIfInvalidAssetData(badAssetData).callAsync()).to.eventually.be.rejectedWith( - StringRevertError, - ); + await expect(devUtils.revertIfInvalidAssetData(badAssetData).callAsync()).to.revertWith('WRONG_PROXY_ID'); }); it('should revert for invalid assetData with valid assetProxyId', async () => { @@ -245,8 +244,8 @@ blockchainTests.resets('LibAssetData', env => { for (const data of assetData) { const badData = data.substring(0, data.length - 2); // drop one byte but retain assetProxyId - await expect(libAssetData.revertIfInvalidAssetData(badData).callAsync()).to.eventually.be.rejectedWith( - LibBytesRevertErrors.InvalidByteOperationError, + await expect(devUtils.revertIfInvalidAssetData(badData).callAsync()).to.revertWith( + new LibBytesRevertErrors.InvalidByteOperationError(), ); } }); @@ -254,33 +253,31 @@ blockchainTests.resets('LibAssetData', env => { describe('getBalance', () => { it('should query ERC20 balance by asset data', async () => { - const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( constants.INITIAL_ERC20_BALANCE, ); }); it('should return 0 if ERC20 token does not exist', async () => { - const assetData = await libAssetData.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync(); - const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync(); + const assetData = await devUtils.encodeERC20AssetData(constants.NULL_ADDRESS).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync(); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); }); it('should query ERC721 balance by asset data', async () => { - const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); + const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); }); it('should return 0 if ERC721 token does not exist', async () => { - const assetData = await libAssetData - .encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId) - .callAsync(); - const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync(); + const assetData = await devUtils.encodeERC721AssetData(constants.NULL_ADDRESS, erc721TokenId).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync(); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); }); it('should query ERC1155 balances by asset data', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeERC1155AssetData( erc1155Token.address, [erc1155TokenId], @@ -288,11 +285,11 @@ blockchainTests.resets('LibAssetData', env => { constants.NULL_BYTES, ) .callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); }); it('should return 0 if ERC1155 token does not exist', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeERC1155AssetData( constants.NULL_ADDRESS, [erc1155TokenId], @@ -300,84 +297,84 @@ blockchainTests.resets('LibAssetData', env => { constants.NULL_BYTES, ) .callAsync(); - const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync(); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); }); it('should query multi-asset batch balance by asset data', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [new BigNumber(1), new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), - await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), ], ) .callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); }); it('should query multi-asset batch balance by asset data, skipping over a nested asset if its amount == 0', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [constants.ZERO_AMOUNT, new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), - await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), ], ) .callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal(1); }); it('should return a balance of 0 if the balance for a nested asset is 0', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [new BigNumber(1), new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(), - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), ], ) .callAsync(); - expect(await libAssetData.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + expect(await devUtils.getBalance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( constants.ZERO_AMOUNT, ); }); it('should return a balance of 0 if the assetData does not correspond to an AssetProxy contract', async () => { const fakeAssetData = '0x01020304'; - const balance = await libAssetData.getBalance(tokenOwner.address, fakeAssetData).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, fakeAssetData).callAsync(); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); }); it('should return a balance of MAX_UINT256 if the the StaticCallProxy assetData contains data for a successful staticcall', async () => { const staticCallData = staticCallTarget.isOddNumber(new BigNumber(1)).getABIEncodedTransactionData(); const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1)); - const assetData = await libAssetData + const assetData = await devUtils .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash) .callAsync(); - const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync(); expect(balance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); it('should return a balance of 0 if the the StaticCallProxy assetData contains data for an unsuccessful staticcall', async () => { const staticCallData = staticCallTarget.isOddNumber(new BigNumber(0)).getABIEncodedTransactionData(); const expectedResultHash = hexUtils.hash(hexUtils.leftPad(1)); - const assetData = await libAssetData + const assetData = await devUtils .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, expectedResultHash) .callAsync(); - const balance = await libAssetData.getBalance(tokenOwner.address, assetData).callAsync(); + const balance = await devUtils.getBalance(tokenOwner.address, assetData).callAsync(); expect(balance).to.bignumber.equal(constants.ZERO_AMOUNT); }); }); describe('getAssetProxyAllowance', () => { it('should query ERC20 allowances by asset data', async () => { - const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(constants.MAX_UINT256); + const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + constants.MAX_UINT256, + ); }); it('should query ERC721 approval by asset data', async () => { @@ -390,21 +387,21 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(1); + const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + 1, + ); }); it('should query ERC721 approvalForAll by assetData', async () => { - const assetData = await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + const assetData = await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + ); }); it('should query ERC1155 allowances by asset data', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeERC1155AssetData( erc1155Token.address, [erc1155TokenId], @@ -412,9 +409,9 @@ blockchainTests.resets('LibAssetData', env => { constants.NULL_BYTES, ) .callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + ); }); it('should query multi-asset allowances by asset data', async () => { @@ -424,18 +421,18 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [new BigNumber(1), new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), - await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), ], ) .callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(1); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + 1, + ); return; }); @@ -446,60 +443,60 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [constants.ZERO_AMOUNT, new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), - await libAssetData.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC721AssetData(erc721Token.address, erc721TokenId).callAsync(), ], ) .callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + ); return; }); it('should return an allowance of 0 if the allowance for a nested asset is 0', async () => { - const assetData = await libAssetData + const assetData = await devUtils .encodeMultiAssetData( [new BigNumber(1), new BigNumber(1)], [ - await libAssetData.encodeERC20AssetData(secondErc20Token.address).callAsync(), - await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(), + await devUtils.encodeERC20AssetData(secondErc20Token.address).callAsync(), + await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(), ], ) .callAsync(); - expect( - await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), - ).to.bignumber.equal(constants.ZERO_AMOUNT); + expect(await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync()).to.bignumber.equal( + constants.ZERO_AMOUNT, + ); }); it('should return an allowance of 0 if the assetData does not correspond to an AssetProxy contract', async () => { const fakeAssetData = '0x01020304'; - const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync(); + const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, fakeAssetData).callAsync(); expect(allowance).to.bignumber.equal(constants.ZERO_AMOUNT); }); it('should return an allowance of MAX_UINT256 for any staticCallAssetData', async () => { const staticCallData = AssetProxyId.StaticCall; - const assetData = await libAssetData + const assetData = await devUtils .encodeStaticCallAssetData(staticCallTarget.address, staticCallData, constants.KECCAK256_NULL) .callAsync(); - const allowance = await libAssetData.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(); + const allowance = await devUtils.getAssetProxyAllowance(tokenOwner.address, assetData).callAsync(); expect(allowance).to.bignumber.equal(constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS); }); }); describe('getBatchBalances', () => { it('should query balances for a batch of asset data strings', async () => { - const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); - const erc721AssetData = await libAssetData + const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); + const erc721AssetData = await devUtils .encodeERC721AssetData(erc721Token.address, erc721TokenId) .callAsync(); expect( - await libAssetData.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(), + await devUtils.getBatchBalances(tokenOwner.address, [erc20AssetData, erc721AssetData]).callAsync(), ).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), new BigNumber(1)]); }); }); @@ -512,9 +509,9 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); + const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); expect( - await libAssetData.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), + await devUtils.getBalanceAndAssetProxyAllowance(tokenOwner.address, assetData).callAsync(), ).to.deep.equal([new BigNumber(constants.INITIAL_ERC20_BALANCE), allowance]); }); }); @@ -526,9 +523,9 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const assetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); + const assetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); expect( - await libAssetData.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(), + await devUtils.getBatchBalancesAndAssetProxyAllowances(tokenOwner.address, [assetData]).callAsync(), ).to.deep.equal([[new BigNumber(constants.INITIAL_ERC20_BALANCE)], [allowance]]); }); }); @@ -541,12 +538,12 @@ blockchainTests.resets('LibAssetData', env => { .awaitTransactionSuccessAsync({ from: tokenOwner.address, }); - const erc20AssetData = await libAssetData.encodeERC20AssetData(erc20Token.address).callAsync(); - const erc721AssetData = await libAssetData + const erc20AssetData = await devUtils.encodeERC20AssetData(erc20Token.address).callAsync(); + const erc721AssetData = await devUtils .encodeERC721AssetData(erc721Token.address, erc721TokenId) .callAsync(); expect( - await libAssetData + await devUtils .getBatchAssetProxyAllowances(tokenOwner.address, [erc20AssetData, erc721AssetData]) .callAsync(), ).to.deep.equal([allowance, constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS]); diff --git a/contracts/integrations/test/dev-utils/lib_transaction_decoder.ts b/contracts/integrations/test/dev-utils/lib_transaction_decoder.ts index 5e23eda5c8..98313cd893 100644 --- a/contracts/integrations/test/dev-utils/lib_transaction_decoder.ts +++ b/contracts/integrations/test/dev-utils/lib_transaction_decoder.ts @@ -1,14 +1,8 @@ -import { ExchangeContract } from '@0x/contracts-exchange'; -import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils'; -import { BlockchainLifecycle } from '@0x/dev-utils'; +import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange'; +import { blockchainTests, constants, expect } from '@0x/contracts-test-utils'; import { BigNumber } from '@0x/utils'; -import * as chai from 'chai'; -import { artifacts, LibTransactionDecoderContract } from '@0x/contracts-dev-utils'; - -chaiSetup.configure(); -const expect = chai.expect; -const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper); +import { artifacts, DevUtilsContract } from '@0x/contracts-dev-utils'; const order = { makerAddress: '0xe36ea790bc9d7ab70c55260c66d52b1eca985f84', @@ -30,25 +24,31 @@ const takerAssetFillAmount = new BigNumber('100000000000000000000'); const signature = '0x1ce8e3c600d933423172b5021158a6be2e818613ff8e762d70ef490c752fd98a626a215f09f169668990414de75a53da221c294a3002f796d004827258b641876e03'; -describe('LibTransactionDecoder', () => { - let libTxDecoder: LibTransactionDecoderContract; - const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, provider, txDefaults); +blockchainTests('LibTransactionDecoder', env => { + let devUtils: DevUtilsContract; + const exchangeInterface = new ExchangeContract(constants.NULL_ADDRESS, { isEIP1193: true } as any); before(async () => { - await blockchainLifecycle.startAsync(); - libTxDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync( - artifacts.LibTransactionDecoder, - provider, - txDefaults, + const exchange = await ExchangeContract.deployFrom0xArtifactAsync( + exchangeArtifacts.Exchange, + env.provider, + env.txDefaults, + exchangeArtifacts, + new BigNumber(1), + ); + devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( + artifacts.DevUtils, artifacts, + env.provider, + env.txDefaults, + artifacts, + exchange.address, + constants.NULL_ADDRESS, ); }); - after(async () => { - await blockchainLifecycle.revertAsync(); - }); it('should decode an Exchange.batchCancelOrders() transaction', async () => { const input = exchangeInterface.batchCancelOrders([order, order]).getABIEncodedTransactionData(); - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ 'batchCancelOrders', [order, order], [], @@ -61,7 +61,7 @@ describe('LibTransactionDecoder', () => { [func]([order, order], [takerAssetFillAmount, takerAssetFillAmount], [signature, signature]) .getABIEncodedTransactionData(); it(`should decode an Exchange.${func}() transaction`, async () => { - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ func, [order, order], [takerAssetFillAmount, takerAssetFillAmount], @@ -72,7 +72,7 @@ describe('LibTransactionDecoder', () => { it('should decode an Exchange.cancelOrder() transaction', async () => { const input = exchangeInterface.cancelOrder(order).getABIEncodedTransactionData(); - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ 'cancelOrder', [order], [], @@ -85,7 +85,7 @@ describe('LibTransactionDecoder', () => { [func](order, takerAssetFillAmount, signature) .getABIEncodedTransactionData(); it(`should decode an Exchange.${func}() transaction`, async () => { - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ func, [order], [takerAssetFillAmount], @@ -104,7 +104,7 @@ describe('LibTransactionDecoder', () => { [func]([order, order], takerAssetFillAmount, [signature, signature]) .getABIEncodedTransactionData(); it(`should decode an Exchange.${func}() transaction`, async () => { - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ func, [order, order], [takerAssetFillAmount], @@ -130,7 +130,7 @@ describe('LibTransactionDecoder', () => { const input = exchangeInterface .matchOrders(order, complementaryOrder, signature, signature) .getABIEncodedTransactionData(); - expect(await libTxDecoder.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ + expect(await devUtils.decodeZeroExTransactionData(input).callAsync()).to.deep.equal([ 'matchOrders', [order, complementaryOrder], [order.takerAssetAmount, complementaryOrder.takerAssetAmount], diff --git a/contracts/integrations/test/framework/deployment_manager.ts b/contracts/integrations/test/framework/deployment_manager.ts index f76b7b3bc0..4b0dd9aa8b 100644 --- a/contracts/integrations/test/framework/deployment_manager.ts +++ b/contracts/integrations/test/framework/deployment_manager.ts @@ -195,8 +195,9 @@ export class DeploymentManager { exchange, staking.stakingProxy, ]); - const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync( + const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( devUtilsArtifacts.DevUtils, + devUtilsArtifacts, environment.provider, environment.txDefaults, devUtilsArtifacts, diff --git a/packages/abi-gen/templates/TypeScript/contract.handlebars b/packages/abi-gen/templates/TypeScript/contract.handlebars index f85a7f6dd4..c3b83c41f4 100644 --- a/packages/abi-gen/templates/TypeScript/contract.handlebars +++ b/packages/abi-gen/templates/TypeScript/contract.handlebars @@ -55,6 +55,7 @@ export enum {{contractName}}Events { {{/if}} /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class {{contractName}}Contract extends BaseContract { diff --git a/packages/contract-addresses/CHANGELOG.json b/packages/contract-addresses/CHANGELOG.json index 3c0f74274b..709fa4810d 100644 --- a/packages/contract-addresses/CHANGELOG.json +++ b/packages/contract-addresses/CHANGELOG.json @@ -5,6 +5,14 @@ { "note": "Update `ERC20BridgeSampler` on mainnet and kovan.", "pr": 2459 + }, + { + "note": "Remove `libTransactionDecoder`", + "pr": 2456 + }, + { + "note": "Update snapshot addresses", + "pr": 2464 } ] }, diff --git a/packages/contract-addresses/addresses.json b/packages/contract-addresses/addresses.json index 9770dc7f9d..2f5a2a464d 100644 --- a/packages/contract-addresses/addresses.json +++ b/packages/contract-addresses/addresses.json @@ -13,7 +13,6 @@ "dutchAuction": "0x0000000000000000000000000000000000000000", "coordinatorRegistry": "0x45797531b873fd5e519477a070a955764c1a5b07", "coordinator": "0x38a795580d0f687e399913a00ddef6a17612c722", - "libTransactionDecoder": "0x5f20e82643ce007d87692eb1b3d3fc059588b224", "multiAssetProxy": "0xef701d5389ae74503d633396c4d654eabedc9d78", "staticCallProxy": "0x3517b88c19508c08650616019062b898ab65ed29", "erc1155Proxy": "0x7eefbd48fd63d441ec7435d024ec7c5131019add", @@ -43,7 +42,6 @@ "dutchAuction": "0x0000000000000000000000000000000000000000", "coordinatorRegistry": "0x403cc23e88c17c4652fb904784d1af640a6722d9", "coordinator": "0x6ff734d96104965c9c1b0108f83abc46e6e501df", - "libTransactionDecoder": "0xb20f3b07afb0e38b6151b9be4f53218bdd7dc231", "multiAssetProxy": "0xab8fbd189c569ccdee3a4d929bb7f557be4028f6", "staticCallProxy": "0xe1b97e47aa3796276033a5341e884d2ba46b6ac1", "erc1155Proxy": "0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d", @@ -69,7 +67,6 @@ "assetProxyOwner": "0x0000000000000000000000000000000000000000", "zeroExGovernor": "0x3f46b98061a3e1e1f41dff296ec19402c298f8a9", "forwarder": "0xd67f2f346f6e85db70632d9f18f50e04192ab54d", - "libTransactionDecoder": "0x34b37611db8190469b735fb2a007d8236c29eb88", "orderValidator": "0x0000000000000000000000000000000000000000", "dutchAuction": "0x0000000000000000000000000000000000000000", "coordinatorRegistry": "0x1084b6a398e47907bae43fec3ff4b677db6e4fee", @@ -100,7 +97,6 @@ "zeroExGovernor": "0x6ff734d96104965c9c1b0108f83abc46e6e501df", "forwarder": "0x2759a4c639fa4882d6d64973630ef81faf901d27", "orderValidator": "0x0000000000000000000000000000000000000000", - "libTransactionDecoder": "0x067b5997c9058eade0bb03d8fb5e6db7feda80a3", "dutchAuction": "0x0000000000000000000000000000000000000000", "coordinatorRegistry": "0x09fb99968c016a3ff537bf58fb3d9fe55a7975d5", "coordinator": "0xd29e59e51e8ab5f94121efaeebd935ca4214e257", @@ -127,21 +123,20 @@ "etherToken": "0x0b1ba0af832d7c05fd64161e0db78e85978e8082", "exchange": "0x48bacb9266a570d521063ef5dd96e61686dbe788", "assetProxyOwner": "0x0000000000000000000000000000000000000000", - "erc20BridgeProxy": "0x8ea76477cfaca8f7ea06477fd3c09a740ac6012a", + "erc20BridgeProxy": "0x038f9b392fb9a9676dbaddf78ea5fdbf6c7d9710", "zeroExGovernor": "0x0000000000000000000000000000000000000000", - "libTransactionDecoder": "0xb48e1b16829c7f5bd62b76cb878a6bb1c4625d7a", - "forwarder": "0x5d3ad3561a1235273cbcb4e82fce63a0073d19be", + "forwarder": "0xe704967449b57b2382b7fa482718748c13c63190", "orderValidator": "0x0000000000000000000000000000000000000000", "dutchAuction": "0x0000000000000000000000000000000000000000", "coordinatorRegistry": "0xaa86dda78e9434aca114b6676fc742a18d15a1cc", "coordinator": "0x4d3d5c850dd5bd9d6f4adda3dd039a3c8054ca29", "multiAssetProxy": "0xcfc18cec799fbd1793b5c43e773c98d4d61cc2db", "staticCallProxy": "0x6dfff22588be9b3ef8cf0ad6dc9b84796f9fb45f", - "devUtils": "0xa31e64ea55b9b6bbb9d6a676738e9a5b23149f84", + "devUtils": "0x74341e87b1c4db7d5ed95f92b37509f2525a7a90", "exchangeV2": "0x48bacb9266a570d521063ef5dd96e61686dbe788", - "zrxVault": "0x1941ff73d1154774d87521d2d0aaad5d19c8df60", - "staking": "0x0d8b0dd11f5d34ed41d556def5f841900d5b1c6b", - "stakingProxy": "0x38ef19fdf8e8415f18c307ed71967e19aac28ba1", + "zrxVault": "0xc4df27466183c0fe2a5924d6ea56e334deff146a", + "staking": "0xf23276778860e420acfc18ebeebf7e829b06965c", + "stakingProxy": "0x8a063452f7df2614db1bca3a85ef35da40cf0835", "uniswapBridge": "0x0000000000000000000000000000000000000000", "eth2DaiBridge": "0x0000000000000000000000000000000000000000", "erc20BridgeSampler": "0x0000000000000000000000000000000000000000", diff --git a/packages/contract-addresses/src/index.ts b/packages/contract-addresses/src/index.ts index 4a38643e5d..56d231d8b0 100644 --- a/packages/contract-addresses/src/index.ts +++ b/packages/contract-addresses/src/index.ts @@ -14,7 +14,6 @@ export interface ContractAddresses { forwarder: string; coordinatorRegistry: string; coordinator: string; - libTransactionDecoder: string; multiAssetProxy: string; staticCallProxy: string; erc1155Proxy: string; diff --git a/packages/contract-artifacts/CHANGELOG.json b/packages/contract-artifacts/CHANGELOG.json index cf961239c7..d54064854b 100644 --- a/packages/contract-artifacts/CHANGELOG.json +++ b/packages/contract-artifacts/CHANGELOG.json @@ -1,4 +1,17 @@ [ + { + "version": "3.5.0", + "changes": [ + { + "note": "Update `DevUtils` artifact", + "pr": 2464 + }, + { + "note": "Remove `LibTransactionDecoder` artifact", + "pr": 2464 + } + ] + }, { "version": "3.4.0", "changes": [ diff --git a/packages/contract-artifacts/artifacts/DevUtils.json b/packages/contract-artifacts/artifacts/DevUtils.json index 70d3c69d1c..0c25914b4f 100644 --- a/packages/contract-artifacts/artifacts/DevUtils.json +++ b/packages/contract-artifacts/artifacts/DevUtils.json @@ -5,8 +5,8 @@ "abi": [ { "inputs": [ - { "internalType": "address", "name": "_exchange", "type": "address" }, - { "internalType": "address", "name": "_chaiBridge", "type": "address" } + { "internalType": "address", "name": "exchange_", "type": "address" }, + { "internalType": "address", "name": "chaiBridge_", "type": "address" } ], "payable": false, "stateMutability": "nonpayable", @@ -23,31 +23,11 @@ }, { "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeAssetProxyDispatchError", - "outputs": [ - { - "internalType": "enum LibExchangeRichErrors.AssetProxyDispatchErrorCodes", - "name": "errorCode", - "type": "uint8" - }, - { "internalType": "bytes32", "name": "orderHash", "type": "bytes32" }, - { "internalType": "bytes", "name": "assetData", "type": "bytes" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeAssetProxyExistsError", - "outputs": [ - { "internalType": "bytes4", "name": "assetProxyId", "type": "bytes4" }, - { "internalType": "address", "name": "assetProxyAddress", "type": "address" } - ], + "inputs": [], + "name": "chaiBridgeAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "payable": false, - "stateMutability": "pure", + "stateMutability": "view", "type": "function" }, { @@ -59,33 +39,6 @@ "stateMutability": "pure", "type": "function" }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeAssetProxyTransferError", - "outputs": [ - { "internalType": "bytes32", "name": "orderHash", "type": "bytes32" }, - { "internalType": "bytes", "name": "assetData", "type": "bytes" }, - { "internalType": "bytes", "name": "errorData", "type": "bytes" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeEIP1271SignatureError", - "outputs": [ - { "internalType": "address", "name": "verifyingContractAddress", "type": "address" }, - { "internalType": "bytes", "name": "data", "type": "bytes" }, - { "internalType": "bytes", "name": "signature", "type": "bytes" }, - { "internalType": "bytes", "name": "errorData", "type": "bytes" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, { "constant": true, "inputs": [{ "internalType": "bytes", "name": "assetData", "type": "bytes" }], @@ -140,56 +93,6 @@ "stateMutability": "pure", "type": "function" }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeExchangeInvalidContextError", - "outputs": [ - { - "internalType": "enum LibExchangeRichErrors.ExchangeContextErrorCodes", - "name": "errorCode", - "type": "uint8" - }, - { "internalType": "bytes32", "name": "orderHash", "type": "bytes32" }, - { "internalType": "address", "name": "contextAddress", "type": "address" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeFillError", - "outputs": [ - { - "internalType": "enum LibExchangeRichErrors.FillErrorCodes", - "name": "errorCode", - "type": "uint8" - }, - { "internalType": "bytes32", "name": "orderHash", "type": "bytes32" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeIncompleteFillError", - "outputs": [ - { - "internalType": "enum LibExchangeRichErrors.IncompleteFillErrorCode", - "name": "errorCode", - "type": "uint8" - }, - { "internalType": "uint256", "name": "expectedAssetFillAmount", "type": "uint256" }, - { "internalType": "uint256", "name": "actualAssetFillAmount", "type": "uint256" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, { "constant": true, "inputs": [{ "internalType": "bytes", "name": "assetData", "type": "bytes" }], @@ -203,87 +106,6 @@ "stateMutability": "pure", "type": "function" }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeNegativeSpreadError", - "outputs": [ - { "internalType": "bytes32", "name": "leftOrderHash", "type": "bytes32" }, - { "internalType": "bytes32", "name": "rightOrderHash", "type": "bytes32" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeOrderEpochError", - "outputs": [ - { "internalType": "address", "name": "makerAddress", "type": "address" }, - { "internalType": "address", "name": "orderSenderAddress", "type": "address" }, - { "internalType": "uint256", "name": "currentEpoch", "type": "uint256" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeOrderStatusError", - "outputs": [ - { "internalType": "bytes32", "name": "orderHash", "type": "bytes32" }, - { "internalType": "enum LibOrder.OrderStatus", "name": "orderStatus", "type": "uint8" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeSignatureError", - "outputs": [ - { - "internalType": "enum LibExchangeRichErrors.SignatureErrorCodes", - "name": "errorCode", - "type": "uint8" - }, - { "internalType": "bytes32", "name": "hash", "type": "bytes32" }, - { "internalType": "address", "name": "signerAddress", "type": "address" }, - { "internalType": "bytes", "name": "signature", "type": "bytes" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeSignatureValidatorNotApprovedError", - "outputs": [ - { "internalType": "address", "name": "signerAddress", "type": "address" }, - { "internalType": "address", "name": "validatorAddress", "type": "address" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeSignatureWalletError", - "outputs": [ - { "internalType": "bytes32", "name": "hash", "type": "bytes32" }, - { "internalType": "address", "name": "signerAddress", "type": "address" }, - { "internalType": "bytes", "name": "signature", "type": "bytes" }, - { "internalType": "bytes", "name": "errorData", "type": "bytes" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, { "constant": true, "inputs": [{ "internalType": "bytes", "name": "assetData", "type": "bytes" }], @@ -300,27 +122,33 @@ }, { "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeTransactionError", + "inputs": [{ "internalType": "bytes", "name": "transactionData", "type": "bytes" }], + "name": "decodeZeroExTransactionData", "outputs": [ + { "internalType": "string", "name": "functionName", "type": "string" }, { - "internalType": "enum LibExchangeRichErrors.TransactionErrorCodes", - "name": "errorCode", - "type": "uint8" + "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": "bytes32", "name": "transactionHash", "type": "bytes32" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - }, - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "encoded", "type": "bytes" }], - "name": "decodeTransactionExecutionError", - "outputs": [ - { "internalType": "bytes32", "name": "transactionHash", "type": "bytes32" }, - { "internalType": "bytes", "name": "errorData", "type": "bytes" } + { "internalType": "uint256[]", "name": "takerAssetFillAmounts", "type": "uint256[]" }, + { "internalType": "bytes[]", "name": "signatures", "type": "bytes[]" } ], "payable": false, "stateMutability": "pure", @@ -386,6 +214,42 @@ "stateMutability": "pure", "type": "function" }, + { + "constant": true, + "inputs": [], + "name": "erc1155ProxyAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "erc20ProxyAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "erc721ProxyAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "exchangeAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": false, "inputs": [ @@ -626,7 +490,7 @@ "name": "getSimulatedOrderMakerTransferResults", "outputs": [ { - "internalType": "enum OrderTransferSimulationUtils.OrderTransferResults", + "internalType": "enum LibOrderTransferSimulation.OrderTransferResults", "name": "orderTransferResults", "type": "uint8" } @@ -665,7 +529,7 @@ "name": "getSimulatedOrderTransferResults", "outputs": [ { - "internalType": "enum OrderTransferSimulationUtils.OrderTransferResults", + "internalType": "enum LibOrderTransferSimulation.OrderTransferResults", "name": "orderTransferResults", "type": "uint8" } @@ -704,7 +568,7 @@ "name": "getSimulatedOrdersTransferResults", "outputs": [ { - "internalType": "enum OrderTransferSimulationUtils.OrderTransferResults[]", + "internalType": "enum LibOrderTransferSimulation.OrderTransferResults[]", "name": "orderTransferResults", "type": "uint8[]" } @@ -757,20 +621,19 @@ "payable": false, "stateMutability": "pure", "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "staticCallProxyAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" } ], "devdoc": { "methods": { - "decodeAssetProxyDispatchError(bytes)": { - "details": "Decompose an ABI-encoded AssetProxyDispatchError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode The error code.orderHash Hash of the order being dispatched.assetData Asset data of the order being dispatched." - }, - "decodeAssetProxyExistsError(bytes)": { - "details": "Decompose an ABI-encoded AssetProxyExistsError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "assetProxyId Id of asset proxy.assetProxyAddress The address of the asset proxy." - }, "decodeAssetProxyId(bytes)": { "details": "Decode AssetProxy identifier", "params": { @@ -778,16 +641,6 @@ }, "return": "The AssetProxy identifier" }, - "decodeAssetProxyTransferError(bytes)": { - "details": "Decompose an ABI-encoded AssetProxyTransferError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "orderHash Hash of the order being dispatched.assetData Asset data of the order being dispatched.errorData ABI-encoded revert data from the asset proxy." - }, - "decodeEIP1271SignatureError(bytes)": { - "details": "Decompose an ABI-encoded SignatureValidatorError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "signerAddress The expected signer of the hash.signature The full signature bytes.errorData The revert data thrown by the validator contract." - }, "decodeERC1155AssetData(bytes)": { "details": "Decode ERC-1155 asset data from the format described in the AssetProxy contract specification.", "params": { "assetData": "AssetProxy-compliant asset data describing an ERC-1155 set of assets." }, @@ -808,70 +661,20 @@ "params": { "assetData": "AssetProxy-compliant asset data describing an ERC-721 asset." }, "return": "The ERC-721 AssetProxy identifier, the address of the ERC-721 contract hosting this asset, and the identifier of the specific asset to be traded." }, - "decodeExchangeInvalidContextError(bytes)": { - "details": "Decompose an ABI-encoded OrderStatusError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode Error code that corresponds to invalid maker, taker, or sender.orderHash The order hash.contextAddress The maker, taker, or sender address" - }, - "decodeFillError(bytes)": { - "details": "Decompose an ABI-encoded FillError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode The error code.orderHash The order hash." - }, - "decodeIncompleteFillError(bytes)": { - "details": "Decompose an ABI-encoded IncompleteFillError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "orderHash Hash of the order being filled." - }, "decodeMultiAssetData(bytes)": { "details": "Decode multi-asset data from the format described in the AssetProxy contract specification.", "params": { "assetData": "AssetProxy-compliant data describing a multi-asset basket." }, "return": "The Multi-Asset AssetProxy identifier, an array of the amounts of the assets to be traded, and an array of the AssetProxy-compliant data describing each asset to be traded. Each element of the arrays corresponds to the same-indexed element of the other array." }, - "decodeNegativeSpreadError(bytes)": { - "details": "Decompose an ABI-encoded NegativeSpreadError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "leftOrderHash Hash of the left order being matched.rightOrderHash Hash of the right order being matched." - }, - "decodeOrderEpochError(bytes)": { - "details": "Decompose an ABI-encoded OrderEpochError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "makerAddress The order maker.orderSenderAddress The order sender.currentEpoch The current epoch for the maker." - }, - "decodeOrderStatusError(bytes)": { - "details": "Decompose an ABI-encoded OrderStatusError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "orderHash The order hash.orderStatus The order status." - }, - "decodeSignatureError(bytes)": { - "details": "Decompose an ABI-encoded SignatureError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode The error code.signerAddress The expected signer of the hash.signature The full signature." - }, - "decodeSignatureValidatorNotApprovedError(bytes)": { - "details": "Decompose an ABI-encoded SignatureValidatorNotApprovedError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "signerAddress The expected signer of the hash.validatorAddress The expected validator." - }, - "decodeSignatureWalletError(bytes)": { - "details": "Decompose an ABI-encoded SignatureWalletError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode The error code.signerAddress The expected signer of the hash.signature The full signature bytes.errorData The revert data thrown by the validator contract." - }, "decodeStaticCallAssetData(bytes)": { "details": "Decode StaticCall asset data from the format described in the AssetProxy contract specification.", "params": { "assetData": "AssetProxy-compliant asset data describing a StaticCall asset" }, "return": "The StaticCall AssetProxy identifier, the target address of the StaticCAll, the data to be passed to the target address, and the expected Keccak-256 hash of the static call return data." }, - "decodeTransactionError(bytes)": { - "details": "Decompose an ABI-encoded TransactionError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "errorCode The error code.transactionHash Hash of the transaction." - }, - "decodeTransactionExecutionError(bytes)": { - "details": "Decompose an ABI-encoded TransactionExecutionError.", - "params": { "encoded": "ABI-encoded revert error." }, - "return": "transactionHash Hash of the transaction.errorData Error thrown by exeucteTransaction()." + "decodeZeroExTransactionData(bytes)": { + "details": "Decodes the call data for an Exchange contract method call.", + "params": { "transactionData": "ABI-encoded calldata for an Exchange contract method call." }, + "return": "The name of the function called, and the parameters it was given. For single-order fills and cancels, the arrays will have just one element." }, "encodeERC1155AssetData(address,uint256[],uint256[],bytes)": { "details": "Encode ERC-1155 asset data into the format described in the AssetProxy contract specification.", @@ -1010,7 +813,7 @@ "return": "The indices of the first failed transfer (or 4 if all transfers are successful) for each order." }, "getTransferableAssetAmount(address,bytes)": { - "details": "Gets the amount of an asset transferable by the owner.", + "details": "Gets the amount of an asset transferable by the maker of an order.", "params": { "assetData": "Description of tokens, per the AssetProxy contract specification.", "ownerAddress": "Address of the owner of the asset." @@ -1025,10 +828,10 @@ }, "evm": { "bytecode": { - "object": "0x60806040523480156200001157600080fd5b5060405162005cff38038062005cff833981016040819052620000349162000409565b600080546001600160a01b0319166001600160a01b0384811691909117808355604051630c0e082160e31b81528392869286928492839285929116906360704108906200008d90630f47261b60e41b9060040162000447565b60206040518083038186803b158015620000a657600080fd5b505afa158015620000bb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620000e19190810190620003d9565b600180546001600160a01b0319166001600160a01b03928316179055600054604051630c0e082160e31b81529116906360704108906200012d9063012b8bc960e11b9060040162000447565b60206040518083038186803b1580156200014657600080fd5b505afa1580156200015b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001819190810190620003d9565b600280546001600160a01b0319166001600160a01b03928316179055600054604051630c0e082160e31b8152911690636070410890620001cd9063a7cb5fb760e01b9060040162000447565b60206040518083038186803b158015620001e657600080fd5b505afa158015620001fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002219190810190620003d9565b600380546001600160a01b0319166001600160a01b03928316179055600054604051630c0e082160e31b81529116906360704108906200026d9063619ce88560e11b9060040162000447565b60206040518083038186803b1580156200028657600080fd5b505afa1580156200029b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002c19190810190620003d9565b600480546001600160a01b03199081166001600160a01b039384161790915560058054821693831693909317909255600680549092169381169390931790555060009250831615905062000316578162000318565b305b9050620003736040518060400160405280600b81526020016a0c1e08141c9bdd1bd8dbdb60aa1b815250604051806040016040528060058152602001640332e302e360dc1b81525085846200038260201b620034e61760201c565b60075550620004759350505050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b600060208284031215620003eb578081fd5b81516001600160a01b038116811462000402578182fd5b9392505050565b600080604083850312156200041c578081fd5b825162000429816200045c565b60208401519092506200043c816200045c565b809150509250929050565b6001600160e01b031991909116815260200190565b6001600160a01b03811681146200047257600080fd5b50565b61587a80620004856000396000f3fe608060405234801561001057600080fd5b50600436106102f45760003560e01c80639a7e752611610191578063ca49f47c116100e3578063d3d862d111610097578063e4e6e7da11610071578063e4e6e7da1461077e578063e77286eb1461079f578063ee4f5a94146107c1576102f4565b8063d3d862d114610729578063d46950281461073c578063e25cabf71461075c576102f4565b8063d001c5dc116100c8578063d001c5dc146106f0578063d186037f14610703578063d363790514610716576102f4565b8063ca49f47c146106ac578063cafd3a07146106cf576102f4565b8063a6627e9f11610145578063bbb2dcf61161011f578063bbb2dcf614610661578063bc03f96414610683578063c26cfecd146106a4576102f4565b8063a6627e9f14610618578063acaedc741461062b578063b43cffe11461064e576102f4565b8063a070cac811610176578063a070cac8146105d2578063a0901e51146105e5578063a5cd62ba146105f8576102f4565b80639a7e75261461058b5780639eadc835146105ae576102f4565b80634dfdac201161024a5780637914b2ec116101fe5780637b66ad34116101d85780637b66ad34146105445780637d727512146105655780638f4ce47914610578576102f4565b80637914b2ec146104f05780637982653e1461051157806379c9c42614610531576102f4565b806363eb39921161022f57806363eb39921461049857806365129042146104ab578063750bdb30146104cd576102f4565b80634dfdac2014610458578063590aa87514610478576102f4565b8063314853ff116102ac5780633db6dc61116102865780633db6dc61146103ff578063459be5e21461042257806346eb65cb14610443576102f4565b8063314853ff146103a8578063327d3054146103ca57806332aae3ad146103dd576102f4565b80630d7b7d76116102dd5780630d7b7d7614610345578063165979e1146103665780632322cf7614610388576102f4565b806302d0aec3146102f957806304a5618a14610323575b600080fd5b61030c610307366004614a21565b6107e3565b60405161031a92919061535e565b60405180910390f35b610336610331366004614a21565b61083f565b60405161031a93929190615488565b610358610353366004614603565b6108ba565b60405161031a92919061530c565b610379610374366004614a21565b6108dc565b60405161031a939291906155c3565b61039b610396366004614603565b610939565b60405161031a91906152c9565b6103bb6103b6366004614a21565b610961565b60405161031a93929190615333565b6103586103d8366004614a21565b6109a8565b6103f06103eb366004614a21565b6109ea565b60405161031a93929190615539565b61041261040d366004614a21565b610a3d565b60405161031a94939291906152d2565b610435610430366004614a21565b610a87565b60405161031a9291906155ac565b610456610451366004614a21565b610add565b005b61046b61046636600461452a565b610c5f565b60405161031a9190615263565b61048b610486366004614341565b610ce2565b60405161031a91906154e8565b61048b6104a6366004614647565b610d52565b6104be6104b9366004614a21565b610dc8565b60405161031a9392919061502f565b6104e06104db366004614a21565b610e02565b60405161031a94939291906153b3565b6105036104fe366004614a21565b610e99565b60405161031a929190615390565b61052461051f366004614ab8565b610ed1565b60405161031a91906155de565b61039b61053f366004614bc0565b61118c565b610557610552366004614a21565b611215565b60405161031a929190615015565b61039b610573366004614603565b61124d565b610503610586366004614a21565b6118a4565b61059e610599366004614a21565b61191a565b60405161031a94939291906155f2565b6105c16105bc366004614a21565b61197b565b60405161031a9594939291906153ef565b61039b6105e0366004614b67565b611a0c565b61046b6105f33660046146c9565b611a8d565b61060b6106063660046146fc565b611b06565b60405161031a919061517b565b61048b61062636600461469e565b611bc9565b61063e610639366004614a21565b611c22565b60405161031a94939291906150d7565b61048b61065c366004614578565b611c5e565b61067461066f366004614a21565b611cd6565b60405161031a939291906154b3565b610696610691366004614a21565b611d50565b60405161031a92919061531a565b61039b611d89565b6106bf6106ba366004614a21565b611d8f565b60405161031a9493929190615445565b6106e26106dd366004614a21565b611e19565b60405161031a929190615629565b61046b6106fe36600461452a565b611e67565b61039b610711366004614603565b611ed5565b610524610724366004614ab8565b6126c7565b61048b6107373660046147cd565b612a77565b61074f61074a366004614a21565b612a96565b60405161031a919061537b565b61076f61076a366004614776565b612b91565b60405161031a939291906151c8565b61079161078c36600461452a565b612cc9565b60405161031a9291906152a4565b6107b26107ad366004614b10565b612ce2565b60405161031a939291906156db565b6107d46107cf366004614a21565b612fa4565b60405161031a93929190615582565b6000806107f7836107f2612fe1565b613005565b600061081060048551866130459092919063ffffffff16565b80602001905161082391908101906149d4565b909350905060ff8116600681111561083757fe5b915050915091565b60008080610853848263ffffffff61308816565b92506001600160e01b0319831663012b8bc960e11b1461088e5760405162461bcd60e51b8152600401610885906156a4565b60405180910390fd5b61089f84601063ffffffff6130bc16565b91506108b284602463ffffffff6130ef16565b929491935050565b6000806108c7848461124d565b91506108d38484611ed5565b90509250929050565b60008060006108ed846107f26130fb565b600061090660048651876130459092919063ffffffff16565b8060200190516109199190810190614d92565b9094509250905060ff8116600281111561092f57fe5b9350509193909250565b600080600061094885856108ba565b91509150610956828261311f565b925050505b92915050565b6000606080610972846107f2613135565b835161098890859060049063ffffffff61304516565b80602001905161099b9190810190614974565b9196909550909350915050565b6000806109b7836107f2613159565b82516109cd90849060049063ffffffff61304516565b8060200190516109e09190810190614916565b9094909350915050565b60008060606109fb846107f261317d565b6000610a1460048651876130459092919063ffffffff16565b806020019051610a279190810190614d52565b9094509250905060ff8116600181111561092f57fe5b600080606080610a4f856107f26131a1565b8451610a6590869060049063ffffffff61304516565b806020019051610a7891908101906148d2565b92989197509550909350915050565b600080610a96836107f26131c5565b6000610aaf60048551866130459092919063ffffffff16565b806020019051610ac29190810190614c90565b9250905060ff81166003811115610ad557fe5b925050915091565b6000610aef828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610b3357610b2c826118a4565b5050610c5b565b6001600160e01b0319811663012b8bc960e11b1415610b5d57610b558261083f565b505050610c5b565b6001600160e01b031981167fa7cb5fb7000000000000000000000000000000000000000000000000000000001415610ba257610b988261197b565b5050505050610c5b565b6001600160e01b031981166394cfcdd760e01b1415610bc457610b5582611cd6565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415610c0857610bff82611d8f565b50505050610c5b565b6001600160e01b031981167fdc1600f3000000000000000000000000000000000000000000000000000000001415610c4357610bff82610e02565b60405162461bcd60e51b8152600401610885906156a4565b5050565b606060008251905080604051908082528060200260200182016040528015610c91578160200160208202803883390190505b50915060005b818114610cda57610cbb85858381518110610cae57fe5b6020026020010151611ed5565b838281518110610cc757fe5b6020908102919091010152600101610c97565b505092915050565b6040516060907ff47261b00000000000000000000000000000000000000000000000000000000090610d18908490602401615001565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b919050565b6040516060907fc339d10a0000000000000000000000000000000000000000000000000000000090610d8c908690869086906024016150a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b9392505050565b6000806000610dd9846107f26131e9565b8351610def90859060049063ffffffff61304516565b80602001905161099b91908101906143f8565b600080806060610e18858363ffffffff61308816565b93506001600160e01b031984167fdc1600f30000000000000000000000000000000000000000000000000000000014610e635760405162461bcd60e51b8152600401610885906156a4565b8451610e7990869060049063ffffffff61320d16565b806020019051610e8c9190810190614396565b9597919650949350915050565b600080610ea8836107f261328d565b8251610ebe90849060049063ffffffff61304516565b8060200190516109e091908101906149f8565b6000610edb613f0c565b610f6c8584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b505afa158015610f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f669190810190614c78565b3a6132b1565b60408051600280825260608281019093529293509091816020015b6060815260200190600190039081610f8757505060408051600280825260608083018452939450909160208301908038833950506040805160028082526060808301845294955090925090602083019080388339505060408051600280825260608083018452949550909250906020830190803883390190505090508861014001518460008151811061101657fe5b602002602001018190525088600001518360008151811061103357fe5b6001600160a01b039283166020918202929092010152881615611056578761106c565b73377f698c4c287018d09b516f415317aec59193325b8260008151811061107957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460000151816000815181106110ab57fe5b602002602001018181525050886101800151846001815181106110ca57fe5b60200260200101819052508860000151836001815181106110e757fe5b6001600160a01b03928316602091820292909201015260408a01511615611112578860400151611128565b73377f698c4c287018d09b516f415317aec59193325b8260018151811061113557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160018151811061116757fe5b60200260200101818152505061117f84848484613328565b9998505050505050505050565b600061120d846112086040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b61353d565b949350505050565b600080611224836107f2613551565b825161123a90849060049063ffffffff61304516565b8060200190516109e0919081019061435d565b600080611260838263ffffffff61308816565b90506001600160e01b031981167ff47261b00000000000000000000000000000000000000000000000000000000014156112bb5760006112a784601063ffffffff6130bc16565b90506112b38186613575565b92505061189d565b6001600160e01b0319811663012b8bc960e11b1415611413576000806112e08561083f565b6040519194509250606091507f6352211e000000000000000000000000000000000000000000000000000000009061131c9084906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b03168360405161136d9190614fe5565b600060405180830381855afa9150503d80600081146113a8576040519150601f19603f3d011682016040523d82523d6000602084013e6113ad565b606091505b509150915060008280156113c2575081516020145b6113cd5760006113de565b6113de82600c63ffffffff6130bc16565b9050896001600160a01b0316816001600160a01b031614611400576000611403565b60015b60ff16975050505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156116035760006060806114538661197b565b5081519296509094509250905060005b8181146115f95782818151811061147657fe5b60200260200101516000141561148b576115f1565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b908790859081106114bf57fe5b60200260200101516040516024016114d892919061510b565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060876001600160a01b0316836040516115299190614fe5565b600060405180830381855afa9150503d8060008114611564576040519150601f19603f3d011682016040523d82523d6000602084013e611569565b606091505b5091509150600082801561157e575081516020145b61158957600061159a565b61159a82600063ffffffff6130ef16565b905060008786815181106115aa57fe5b602002602001015182816115ba57fe5b049050806115d65760009b50505050505050505050505061095b565b8b8110806115e257508b155b156115eb57809b505b50505050505b600101611463565b505050505061189d565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415611721576040516060907fa85e59e40000000000000000000000000000000000000000000000000000000090611672908690600090819081906024016154fb565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260045491519092506000916001600160a01b0316906116c4908490614fe5565b600060405180830381855afa9150503d80600081146116ff576040519150601f19603f3d011682016040523d82523d6000602084013e611704565b606091505b5050905080611714576000611718565b6000195b9350505061189d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156117c85760008061175f85610e02565b50925092505061176d613678565b6001600160a01b0316826001600160a01b031614801561179a57506005546001600160a01b038281169116145b156117c15760006117b26117ac613690565b88613575565b90506117bd816136a8565b9450505b505061189d565b6001600160e01b031981166394cfcdd760e01b141561189d576060806117ed85611cd6565b80519194509250905060005b8181146118985783818151811061180c57fe5b60200260200101516000141561182157611890565b60006118408985848151811061183357fe5b602002602001015161124d565b9050600085838151811061185057fe5b6020026020010151828161186057fe5b0490508061187857600097505050505050505061095b565b87811080611884575087155b1561188d578097505b50505b6001016117f9565b505050505b5092915050565b6000806118b7838263ffffffff61308816565b91506001600160e01b031982167ff47261b000000000000000000000000000000000000000000000000000000000146119025760405162461bcd60e51b8152600401610885906156a4565b61191383601063ffffffff6130bc16565b9050915091565b6000806000606061192d856107f26138a6565b600061194660048751886130459092919063ffffffff16565b8060200190516119599190810190614cf4565b91965094509250905060ff8116600681111561197157fe5b9450509193509193565b60008060608080611992868563ffffffff61308816565b94506001600160e01b031985167fa7cb5fb700000000000000000000000000000000000000000000000000000000146119dd5760405162461bcd60e51b8152600401610885906156a4565b505050506024828101516044840151606485015160848601519496929591820184019490820184019391010190565b600061120d84611a886040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b6138ca565b6060808251604051908082528060200260200182016040528015611abb578160200160208202803883390190505b50905060005b8351811461189d57838181518110611ad557fe5b60200260200101516001600160a01b031631828281518110611af357fe5b6020908102919091010152600101611ac1565b606060008451905080604051908082528060200260200182016040528015611b38578160200160208202803883390190505b50915060005b818114611bc057611b89868281518110611b5457fe5b6020026020010151868381518110611b6857fe5b6020026020010151868481518110611b7c57fe5b60200260200101516126c7565b838281518110611b9557fe5b60200260200101906004811115611ba857fe5b90816004811115611bb557fe5b905250600101611b3e565b50509392505050565b60405160609063012b8bc960e11b90611be8908590859060240161510b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905092915050565b60006060806060611c35856107f26138d9565b8451611c4b90869060049063ffffffff61304516565b806020019051610a789190810190614492565b6040516060907fa7cb5fb70000000000000000000000000000000000000000000000000000000090611c9a908790879087908790602401615053565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050949350505050565b6000606080611ceb848463ffffffff61308816565b92506001600160e01b031983166394cfcdd760e01b14611d1d5760405162461bcd60e51b8152600401610885906156a4565b8351611d3390859060049063ffffffff61320d16565b806020019051611d469190810190614802565b9395909450915050565b60006060611d60836107f26138fd565b8251611d7690849060049063ffffffff61304516565b8060200190516109e09190810190614939565b60075481565b600080606081611da5858263ffffffff61308816565b93506001600160e01b031984167fc339d10a0000000000000000000000000000000000000000000000000000000014611df05760405162461bcd60e51b8152600401610885906156a4565b8451611e0690869060049063ffffffff61320d16565b806020019051610e8c919081019061443a565b600080611e28836107f2613921565b6000611e4160048551866130459092919063ffffffff16565b806020019051611e549190810190614c90565b9250905060ff81166001811115610ad557fe5b606060008251905080604051908082528060200260200182016040528015611e99578160200160208202803883390190505b50915060005b818114610cda57611eb68585838151811061183357fe5b838281518110611ec257fe5b6020908102919091010152600101611e9f565b600080611ee8838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b1415611fb857606080611f0f85611cd6565b80519194509250905060005b818114611fad57838181518110611f2e57fe5b602002602001015160001415611f4357611fa5565b6000611f5589858481518110610cae57fe5b90506000858381518110611f6557fe5b60200260200101518281611f7557fe5b04905080611f8d57600097505050505050505061095b565b87811080611f99575087155b15611fa2578097505b50505b600101611f1b565b5061095b9350505050565b6001600160e01b031981167ff47261b000000000000000000000000000000000000000000000000000000000141561210e576000611ffd84601063ffffffff6130bc16565b6001546040519192506060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916120439189916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b0316836040516120949190614fe5565b600060405180830381855afa9150503d80600081146120cf576040519150601f19603f3d011682016040523d82523d6000602084013e6120d4565b606091505b50915091508180156120e7575080516020145b6120f2576000612103565b61210381600063ffffffff6130ef16565b95505050505061189d565b6001600160e01b0319811663012b8bc960e11b1415612373576000806121338561083f565b600254604051929550909350606092507fe985e9c5000000000000000000000000000000000000000000000000000000009161217f918a916001600160a01b0390911690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b0316836040516121d09190614fe5565b600060405180830381855afa9150503d806000811461220b576040519150601f19603f3d011682016040523d82523d6000602084013e612210565b606091505b509150915081158061222457508051602014155b80612240575061223b81600063ffffffff6130ef16565b600114155b15612364576040516060907f081812fc000000000000000000000000000000000000000000000000000000009061227b9087906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050856001600160a01b0316816040516122c89190614fe5565b600060405180830381855afa9150503d8060008114612303576040519150601f19603f3d011682016040523d82523d6000602084013e612308565b606091505b50909350915082801561231c575081516020145b801561234b57506002546001600160a01b031661234083600c63ffffffff6130bc16565b6001600160a01b0316145b612356576000612359565b60015b60ff169750506115f9565b6000199650505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156124d35760006123b08461197b565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926123fa925089916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b03168360405161244b9190614fe5565b600060405180830381855afa9150503d8060008114612486576040519150601f19603f3d011682016040523d82523d6000602084013e61248b565b606091505b509150915081801561249e575080516020145b80156124ba57506124b681600063ffffffff6130ef16565b6001145b6124c5576000612103565b60001995505050505061189d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561250f57600019915061189d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561189d5760008061254d85610e02565b50925092505061255b613678565b6001600160a01b0316826001600160a01b031614801561258857506005546001600160a01b038281169116145b156126be576005546040516060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916125d2918a916001600160a01b0390911690602401615015565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905060006060612612613690565b6001600160a01b0316836040516126299190614fe5565b600060405180830381855afa9150503d8060008114612664576040519150601f19603f3d011682016040523d82523d6000602084013e612669565b606091505b5091509150600082801561267e575081516020145b61268957600061269a565b61269a82600063ffffffff6130ef16565b905060001981146126b3576126ae816136a8565b6126b7565b6000195b9750505050505b50505092915050565b60006126d1613f0c565b6127248584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b60408051600480825260a0820190925291925060609190816020015b606081526020019060019003908161274057505060408051600480825260a082019092529192506060919060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339019050509050886101600151846000815181106127d657fe5b602002602001018190525087836000815181106127ef57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505088600001518260008151811061282157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050868160008151811061284f57fe5b6020026020010181815250508861014001518460018151811061286e57fe5b602002602001018190525088600001518360018151811061288b57fe5b6001600160a01b0392831660209182029290920101528816156128ae57876128c4565b73377f698c4c287018d09b516f415317aec59193325b826001815181106128d157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084600001518160018151811061290357fe5b602002602001018181525050886101a001518460028151811061292257fe5b6020026020010181905250878360028151811061293b57fe5b6001600160a01b03928316602091820292909201015260408a0151161561296657886040015161297c565b73377f698c4c287018d09b516f415317aec59193325b8260028151811061298957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460600151816002815181106129bb57fe5b602002602001018181525050886101800151846003815181106129da57fe5b60200260200101819052508860000151836003815181106129f757fe5b6001600160a01b03928316602091820292909201015260408a01511615612a22578860400151612a38565b73377f698c4c287018d09b516f415317aec59193325b82600381518110612a4557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160038151811061116757fe5b6040516060906394cfcdd760e01b90611be89085908590602401615276565b6000612aa8828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001480612af257506001600160e01b0319811663012b8bc960e11b145b80612b2657506001600160e01b031981167fa7cb5fb700000000000000000000000000000000000000000000000000000000145b80612b4157506001600160e01b031981166394cfcdd760e01b145b80612b7557506001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000145b610d4d5760405162461bcd60e51b8152600401610885906156a4565b606080606060008551905080604051908082528060200260200182016040528015612bd657816020015b612bc3613f3b565b815260200190600190039081612bbb5790505b50935080604051908082528060200260200182016040528015612c03578160200160208202803883390190505b50925080604051908082528060200260200182016040528015612c30578160200160208202803883390190505b50915060005b818114612cc057612c6d878281518110612c4c57fe5b6020026020010151878381518110612c6057fe5b6020026020010151612ce2565b8751889085908110612c7b57fe5b60200260200101878581518110612c8e57fe5b60200260200101878681518110612ca157fe5b9315156020948502919091019093019290925291905252600101612c36565b50509250925092565b606080612cd68484611e67565b91506108d38484610c5f565b612cea613f3b565b6006546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815260009182916001600160a01b0390911690639d3fa4b990612d389088906004016156ff565b60606040518083038186803b158015612d5057600080fd5b505afa158015612d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d889190810190614a70565b85516006546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f90612dda9089908990600401615712565b60206040518083038186803b158015612df257600080fd5b505afa158015612e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e2a91908101906148b2565b91506000612e3d82886101400151610939565b60a088015160c08901516101808a01516101408b015193945091929091600091612e6c9163ffffffff61394516565b15612e9957612e9284612e8c848d6080015161396a90919063ffffffff16565b85613986565b9050612ef2565b81612ead57612e92848b6080015185613986565b6000612ebe868c6101800151610939565b90506000612ed1868d6080015187613986565b90506000612ee0838688613986565b9050612eec828261311f565b93505050505b612f12612f0c8960400151856139a890919063ffffffff16565b8261311f565b96506004612f258b8c602001518a610ed1565b6004811115612f3057fe5b14612f3c576000612f3e565b865b9650612f4e8a61016001516139c7565b612f5757600096505b60e08a015115801590612f755750612f738a6101a001516139c7565b155b15612f7f57600096505b600388516006811115612f8e57fe5b14612f9857600096505b50505050509250925092565b6000806000612fb5846107f2613ab1565b6000612fce60048651876130459092919063ffffffff16565b8060200190516109199190810190614cbd565b7ffdb6ca8d0000000000000000000000000000000000000000000000000000000090565b6000613012836000613088565b90506001600160e01b0319808216908316146130405760405162461bcd60e51b81526004016108859061566d565b505050565b6060818311156130635761306361305e60008585613ad5565b613af4565b835182111561307c5761307c61305e6001848751613ad5565b50819003910190815290565b600081600401835110156130a9576130a961305e6003855185600401613ad5565b5001602001516001600160e01b03191690565b600081601401835110156130dd576130dd61305e6004855185601401613ad5565b5001601401516001600160a01b031690565b6000610dc18383613afc565b7f18e4b1410000000000000000000000000000000000000000000000000000000090565b600081831061312e5781610dc1565b5090919050565b7f4678472b0000000000000000000000000000000000000000000000000000000090565b7fb6555d6f0000000000000000000000000000000000000000000000000000000090565b7f488219a60000000000000000000000000000000000000000000000000000000090565b7f1b8388f70000000000000000000000000000000000000000000000000000000090565b7fe94a7ed00000000000000000000000000000000000000000000000000000000090565b7f4ad312750000000000000000000000000000000000000000000000000000000090565b6060818311156132265761322661305e60008585613ad5565b835182111561323f5761323f61305e6001848751613ad5565b8282036040519080825280601f01601f19166020018201604052801561326c576020820181803883390190505b509050610dc161327b82613b26565b8461328587613b26565b018351613b2c565b7f11c7b7200000000000000000000000000000000000000000000000000000000090565b6132b9613f0c565b6020810184905260a085015160808601516132d5918691613bd1565b815260a085015160c08601516132ec918691613bd1565b604082015260a085015160e0860151613306918691613bd1565b606082015261331b828463ffffffff613c0516565b6080820152949350505050565b6040516000906060907fb04fbddd0000000000000000000000000000000000000000000000000000000090613367908890889088908890602401615124565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260065491519092506060916001600160a01b0316906133b9908490614fe5565b6000604051808303816000865af19150503d80600081146133f6576040519150601f19603f3d011682016040523d82523d6000602084013e6133fb565b606091505b50915060009050613412828263ffffffff61308816565b905061341c61317d565b6001600160e01b03198281169116141561345957600061343b836109ea565b5091505060ff8116600481111561344e57fe5b94505050505061120d565b613461613135565b6001600160e01b03198281169116141561349457600061348083610961565b509091505060ff8116600481111561344e57fe5b815160208301207ff43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce014156134ce576004935050505061120d565b60405162461bcd60e51b815260040161088590615636565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6000610dc18261354c85613c36565b613cb1565b7fa15c0d060000000000000000000000000000000000000000000000000000000090565b6040516000906060907f70a0823100000000000000000000000000000000000000000000000000000000906135ae908590602401615001565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060856001600160a01b0316836040516135ff9190614fe5565b600060405180830381855afa9150503d806000811461363a576040519150601f19603f3d011682016040523d82523d6000602084013e61363f565b606091505b5091509150818015613652575080516020145b61365d57600061366e565b61366e81600063ffffffff6130ef16565b9695505050505050565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b6000806136b3613690565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156136ed57600080fd5b505af1158015613701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506137259190810190614a54565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561376457600080fd5b505af1158015613778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061379c9190810190614c78565b421161381a57816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156137dd57600080fd5b505af11580156137f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506138159190810190614c78565b61388d565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561385557600080fd5b505af1158015613869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061388d9190810190614c78565b905061120d816b033b2e3c9fd0803ce800000086613986565b7f7e5a23180000000000000000000000000000000000000000000000000000000090565b6000610dc18261354c85613ceb565b7f5bd0428d0000000000000000000000000000000000000000000000000000000090565b7f20d11f610000000000000000000000000000000000000000000000000000000090565b7ff59851840000000000000000000000000000000000000000000000000000000090565b600081518351148015610dc15750508051602091820120825192909101919091201490565b600082820183811015610dc157610dc161305e60008686613da4565b600061120d8361399c868563ffffffff613c0516565b9063ffffffff613dc316565b6000828211156139c1576139c161305e60028585613da4565b50900390565b600060208251816139d457fe5b066004146139e457506000610d4d565b60006139f6838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b14613a1a576001915050610d4d565b606080613a2685611cd6565b80519194509250905060005b818114613aa4576000613a626000858481518110613a4c57fe5b602002602001015161308890919063ffffffff16565b90506001600160e01b0319811663012b8bc960e11b1415613a9b57613a878483613ded565b15613a9b5760009650505050505050610d4d565b50600101613a32565b5060019695505050505050565b7fe53c76c80000000000000000000000000000000000000000000000000000000090565b6060632800659560e01b848484604051602401610d8c939291906155d0565b805160208201fd5b60008160200183511015613b1d57613b1d61305e6005855185602001613ad5565b50016020015190565b60200190565b6020811015613b56576001816020036101000a038019835116818551168082178652505050613040565b82821415613b6357613040565b82821115613b9d5760208103905080820181840181515b82851015613b95578451865260209586019590940193613b7a565b905250613040565b60208103905080820181840183515b81861215613bc85782518252601f199283019290910190613bac565b85525050505050565b6000613bde848484613e50565b15613bf157613bf161305e858585613eb6565b61120d8361399c868563ffffffff613c0516565b600082613c145750600061095b565b82820282848281613c2157fe5b0414610dc157610dc161305e60018686613da4565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a753493909290916020871015613d3757fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b606063e946c1bb60e01b848484604051602401610d8c93929190615561565b600081613dd957613dd961305e60038585613da4565b6000828481613de457fe5b04949350505050565b8151600090600183015b81811015610cda57613e38858281518110613e0e57fe5b6020026020010151868681518110613e2257fe5b602002602001015161394590919063ffffffff16565b15613e485760019250505061095b565b600101613df7565b600082613e6257613e6261305e613ed5565b811580613e6d575083155b15613e7a57506000610dc1565b60008380613e8457fe5b8584099050613e99858463ffffffff613c0516565b613eab826103e863ffffffff613c0516565b101595945050505050565b606063339f3de260e01b848484604051602401610d8c93929190615737565b60408051808201909152600481527fa791837c00000000000000000000000000000000000000000000000000000000602082015290565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040805160608101909152806000815260006020820181905260409091015290565b803561095b81615813565b600082601f830112613f78578081fd5b8135613f8b613f8682615774565b61574d565b818152915060208083019084810181840286018201871015613fac57600080fd5b60005b84811015611898578135613fc281615813565b84529282019290820190600101613faf565b600082601f830112613fe4578081fd5b8151613ff2613f8682615774565b8181529150602080830190840160005b8381101561402f5761401a876020845189010161419b565b83526020928301929190910190600101614002565b5050505092915050565b600082601f830112614049578081fd5b8135614057613f8682615774565b8181529150602080830190840160005b8381101561402f5761407f876020843589010161414d565b83526020928301929190910190600101614067565b600082601f8301126140a4578081fd5b81356140b2613f8682615774565b8181529150602080830190840160005b8381101561402f576140da87602084358901016141e1565b835260209283019291909101906001016140c2565b600082601f8301126140ff578081fd5b813561410d613f8682615774565b81815291506020808301908481018184028601820187101561412e57600080fd5b60005b8481101561189857813584529282019290820190600101614131565b600082601f83011261415d578081fd5b813561416b613f8682615794565b915080825283602082850101111561418257600080fd5b8060208401602084013760009082016020015292915050565b600082601f8301126141ab578081fd5b81516141b9613f8682615794565b91508082528360208285010111156141d057600080fd5b61189d8160208401602086016157b8565b60006101c08083850312156141f4578182fd5b6141fd8161574d565b91505061420a8383613f5d565b81526142198360208401613f5d565b602082015261422b8360408401613f5d565b604082015261423d8360608401613f5d565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561429f57600080fd5b6142ab8683870161414d565b838501526101609250828501359150808211156142c757600080fd5b6142d38683870161414d565b838501526101809250828501359150808211156142ef57600080fd5b6142fb8683870161414d565b838501526101a092508285013591508082111561431757600080fd5b506143248582860161414d565b82840152505092915050565b805160ff8116811461095b57600080fd5b600060208284031215614352578081fd5b8135610dc181615813565b6000806040838503121561436f578081fd5b825161437a81615813565b602084015190925061438b81615813565b809150509250929050565b6000806000606084860312156143aa578081fd5b83516143b581615813565b60208501519093506143c681615813565b604085015190925067ffffffffffffffff8111156143e2578182fd5b6143ee8682870161419b565b9150509250925092565b60008060006060848603121561440c578081fd5b835161441781615813565b602085015190935061442881615813565b80925050604084015190509250925092565b60008060006060848603121561444e578081fd5b835161445981615813565b602085015190935067ffffffffffffffff811115614475578182fd5b6144818682870161419b565b925050604084015190509250925092565b600080600080608085870312156144a7578182fd5b84516144b281615813565b602086015190945067ffffffffffffffff808211156144cf578384fd5b6144db8883890161419b565b945060408701519150808211156144f0578384fd5b6144fc8883890161419b565b93506060870151915080821115614511578283fd5b5061451e8782880161419b565b91505092959194509250565b6000806040838503121561453c578182fd5b823561454781615813565b9150602083013567ffffffffffffffff811115614562578182fd5b61456e85828601614039565b9150509250929050565b6000806000806080858703121561458d578182fd5b843561459881615813565b9350602085013567ffffffffffffffff808211156145b4578384fd5b6145c0888389016140ef565b945060408701359150808211156145d5578384fd5b6145e1888389016140ef565b935060608701359150808211156145f6578283fd5b5061451e8782880161414d565b60008060408385031215614615578182fd5b823561462081615813565b9150602083013567ffffffffffffffff81111561463b578182fd5b61456e8582860161414d565b60008060006060848603121561465b578081fd5b833561466681615813565b9250602084013567ffffffffffffffff811115614681578182fd5b61468d8682870161414d565b925050604084013590509250925092565b600080604083850312156146b0578182fd5b82356146bb81615813565b946020939093013593505050565b6000602082840312156146da578081fd5b813567ffffffffffffffff8111156146f0578182fd5b61120d84828501613f68565b600080600060608486031215614710578081fd5b833567ffffffffffffffff80821115614727578283fd5b61473387838801614094565b94506020860135915080821115614748578283fd5b61475487838801613f68565b93506040860135915080821115614769578283fd5b506143ee868287016140ef565b60008060408385031215614788578182fd5b823567ffffffffffffffff8082111561479f578384fd5b6147ab86838701614094565b935060208501359150808211156147c0578283fd5b5061456e85828601614039565b600080604083850312156147df578182fd5b823567ffffffffffffffff808211156147f6578384fd5b6147ab868387016140ef565b60008060408385031215614814578182fd5b825167ffffffffffffffff8082111561482b578384fd5b81850186601f82011261483c578485fd5b8051925061484c613f8684615774565b80848252602080830192508084018a82838902870101111561486c578889fd5b8894505b8685101561488e578051845260019490940193928101928101614870565b5088015190965093505050808211156148a5578283fd5b5061456e85828601613fd4565b6000602082840312156148c3578081fd5b81518015158114610dc1578182fd5b600080600080608085870312156148e7578182fd5b8451935060208501516148f981615813565b604086015190935067ffffffffffffffff808211156144f0578384fd5b60008060408385031215614928578182fd5b505080516020909101519092909150565b6000806040838503121561494b578182fd5b82519150602083015167ffffffffffffffff811115614968578182fd5b61456e8582860161419b565b600080600060608486031215614988578081fd5b83519250602084015167ffffffffffffffff808211156149a6578283fd5b6149b28783880161419b565b935060408601519150808211156149c7578283fd5b506143ee8682870161419b565b600080604083850312156149e6578182fd5b82519150602083015161438b81615828565b60008060408385031215614a0a578182fd5b82516001600160e01b03198116811461437a578283fd5b600060208284031215614a32578081fd5b813567ffffffffffffffff811115614a48578182fd5b61120d8482850161414d565b600060208284031215614a65578081fd5b8151610dc181615813565b600060608284031215614a81578081fd5b614a8b606061574d565b825160078110614a99578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614acc578081fd5b833567ffffffffffffffff811115614ae2578182fd5b614aee868287016141e1565b9350506020840135614aff81615813565b929592945050506040919091013590565b60008060408385031215614b22578182fd5b823567ffffffffffffffff80821115614b39578384fd5b614b45868387016141e1565b93506020850135915080821115614b5a578283fd5b5061456e8582860161414d565b600080600060608486031215614b7b578081fd5b833567ffffffffffffffff811115614b91578182fd5b614b9d868287016141e1565b935050602084013591506040840135614bb581615813565b809150509250925092565b600080600060608486031215614bd4578081fd5b833567ffffffffffffffff80821115614beb578283fd5b81860160a08189031215614bfd578384fd5b614c0760a061574d565b9250803583526020810135602084015260408101356040840152614c2e8860608301613f5d565b6060840152608081013582811115614c44578485fd5b614c508982840161414d565b608085015250919450505060208401359150614c6f8560408601613f5d565b90509250925092565b600060208284031215614c89578081fd5b5051919050565b60008060408385031215614ca2578182fd5b8251614cad81615828565b6020939093015192949293505050565b600080600060608486031215614cd1578081fd5b8351614cdc81615828565b602085015160408601519194509250614bb581615813565b60008060008060808587031215614d09578182fd5b614d138686614330565b9350602085015192506040850151614d2a81615813565b606086015190925067ffffffffffffffff811115614d46578182fd5b61451e8782880161419b565b600080600060608486031215614d66578081fd5b614d708585614330565b925060208401519150604084015167ffffffffffffffff8111156143e2578182fd5b600080600060608486031215614da6578081fd5b614db08585614330565b925060208401519150604084015190509250925092565b6001600160a01b03169052565b6000815180845260208401935060208301825b82811015614e0e5781516001600160a01b0316865260209586019590910190600101614de7565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b84811015614e63578284038852614e4d848351614ea0565b6020988901989094509190910190600101614e35565b50919695505050505050565b6000815180845260208401935060208301825b82811015614e0e578151865260209586019590910190600101614e82565b60008151808452614eb88160208601602086016157b8565b601f01601f19169290920160200192915050565b8051614ed781615809565b825260208181015190830152604090810151910152565b60006101c0614efe848451614dc7565b6020830151614f106020860182614dc7565b506040830151614f236040860182614dc7565b506060830151614f366060860182614dc7565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152614f8f83870182614ea0565b91505061016091508184015185820383870152614fac8282614ea0565b925050506101808084015185830382870152614fc88382614ea0565b9150506101a09150818401518582038387015261366e8282614ea0565b60008251614ff78184602087016157b8565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0386168252608060208301526150756080830186614e6f565b82810360408401526150878186614e6f565b83810360608501526150998186614ea0565b98975050505050505050565b60006001600160a01b0385168252606060208301526150c76060830185614ea0565b9050826040830152949350505050565b60006001600160a01b0386168252608060208301526150f96080830186614ea0565b82810360408401526150878186614ea0565b6001600160a01b03929092168252602082015260400190565b6000608082526151376080830187614e18565b82810360208401526151498187614dd4565b838103604085015261515b8187614dd4565b91505082810360608401526151708185614e6f565b979650505050505050565b602080825282518282018190526000918401906040840190835b818110156151bd578351600581106151a957fe5b835260209384019390920191600101615195565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561520b576151f8848351614ecc565b60609390930192908401906001016151e5565b5050508381038285015261521f8187614e6f565b84810360408601528551808252908301915082860190845b81811015615255578251151584529284019291840191600101615237565b509198975050505050505050565b600060208252610dc16020830184614e6f565b6000604082526152896040830185614e6f565b828103602084015261529b8185614e18565b95945050505050565b6000604082526152b76040830185614e6f565b828103602084015261529b8185614e6f565b90815260200190565b60008582526001600160a01b0385166020830152608060408301526152fa6080830185614ea0565b82810360608401526151708185614ea0565b918252602082015260400190565b60008382526040602083015261120d6040830184614ea0565b60008482526060602083015261534c6060830185614ea0565b828103604084015261366e8185614ea0565b8281526040810161536e83615809565b8260208301529392505050565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261366e6080830184614ea0565b60006001600160e01b0319871682526001600160a01b038616602083015260a0604083015261542160a0830186614e6f565b82810360608401526154338186614e6f565b838103608085015261117f8186614ea0565b60006001600160e01b0319861682526001600160a01b0385166020830152608060408301526154776080830185614ea0565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b031985168252606060208301526154d66060830185614e6f565b828103604084015261366e8185614e18565b600060208252610dc16020830184614ea0565b60006080825261550e6080830187614ea0565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6000615544856157e8565b8482528360208301526060604083015261529b6060830184614ea0565b6060810161556e856157f5565b938152602081019290925260409091015290565b6060810161558f856157ff565b93815260208101929092526001600160a01b031660409091015290565b604081016155b9846157f5565b9281526020015290565b6060810161556e856157ff565b606081016008851061556e57fe5b60208101600583106155ec57fe5b91905290565b60006155fd86615809565b8582528460208301526001600160a01b03841660408301526080606083015261366e6080830184614ea0565b604081016155b9846157e8565b60208082526013908201527f554e4b4e4f574e5f52455455524e5f4441544100000000000000000000000000604082015260600190565b6020808252600c908201527f4241445f53454c4543544f520000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f57524f4e475f50524f58595f4944000000000000000000000000000000000000604082015260600190565b60a081016156e98286614ecc565b8360608301528215156080830152949350505050565b600060208252610dc16020830184614eee565b6000604082526157256040830185614eee565b828103602084015261529b8185614ea0565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561576c57600080fd5b604052919050565b600067ffffffffffffffff82111561578a578081fd5b5060209081020190565b600067ffffffffffffffff8211156157aa578081fd5b50601f01601f191660200190565b60005b838110156157d35781810151838201526020016157bb565b838111156157e2576000848401525b50505050565b600281106157f257fe5b50565b600481106157f257fe5b600381106157f257fe5b600781106157f257fe5b6001600160a01b03811681146157f257600080fd5b60ff811681146157f257600080fdfea365627a7a72315820b8f5e1baee716487ac576e78a6a19b92db1db8535a5a9d8ed8a3c9e3e2968a386c6578706572696d656e74616cf564736f6c63430005100040" + "object": "0x60806040523480156200001157600080fd5b5060405162005228380380620052288339810160408190526200003491620003e5565b600080546001600160a01b03199081166001600160a01b0385811691821784556005805490931690851617909155604051630c0e082160e31b8152829185918591906360704108906200009390630f47261b60e41b9060040162000423565b60206040518083038186803b158015620000ac57600080fd5b505afa158015620000c1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620000e79190810190620003b5565b600180546001600160a01b0319166001600160a01b03928316179055604051630c0e082160e31b815290831690636070410890620001319063012b8bc960e11b9060040162000423565b60206040518083038186803b1580156200014a57600080fd5b505afa1580156200015f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001859190810190620003b5565b600280546001600160a01b0319166001600160a01b03928316179055604051630c0e082160e31b815290831690636070410890620001cf9063a7cb5fb760e01b9060040162000423565b60206040518083038186803b158015620001e857600080fd5b505afa158015620001fd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002239190810190620003b5565b600380546001600160a01b0319166001600160a01b03928316179055604051630c0e082160e31b8152908316906360704108906200026d9063619ce88560e11b9060040162000423565b60206040518083038186803b1580156200028657600080fd5b505afa1580156200029b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002c19190810190620003b5565b600480546001600160a01b0319166001600160a01b03928316179055600092508316159050620002f25781620002f4565b305b90506200034f6040518060400160405280600b81526020016a0c1e08141c9bdd1bd8dbdb60aa1b815250604051806040016040528060058152602001640332e302e360dc1b81525085846200035e60201b620029c31760201c565b60065550620004519350505050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b600060208284031215620003c7578081fd5b81516001600160a01b0381168114620003de578182fd5b9392505050565b60008060408385031215620003f8578081fd5b8251620004058162000438565b6020840151909250620004188162000438565b809150509250929050565b6001600160e01b031991909116815260200190565b6001600160a01b03811681146200044e57600080fd5b50565b614dc780620004616000396000f3fe608060405234801561001057600080fd5b506004361061025c5760003560e01c8063a5cd62ba11610145578063d3637905116100bd578063e4e6e7da1161008c578063ee18599711610071578063ee185997146105b5578063ef3bb097146105bd578063ff84e7cc146105c55761025c565b8063e4e6e7da14610572578063e77286eb146105935761025c565b8063d36379051461050a578063d3d862d11461051d578063d469502814610530578063e25cabf7146105505761025c565b8063c26cfecd11610114578063ca49f47c116100f9578063ca49f47c146104c1578063d001c5dc146104e4578063d186037f146104f75761025c565b8063c26cfecd146104b1578063c82037ef146104b95761025c565b8063a5cd62ba14610449578063a6627e9f14610469578063b43cffe11461047c578063bbb2dcf61461048f5761025c565b80637982653e116101d85780639baf2705116101a75780639eadc8351161018c5780639eadc835146103ff578063a070cac814610423578063a0901e51146104365761025c565b80639baf2705146103e25780639cd01605146103f75761025c565b80637982653e1461037b57806379c9c4261461039b5780637d727512146103ae5780638f4ce479146103c15761025c565b80634dfdac201161022f57806363eb39921161021457806363eb3992146103225780636f83188e14610335578063750bdb30146103585761025c565b80634dfdac20146102e2578063590aa875146103025761025c565b806304a5618a146102615780630d7b7d761461028c5780632322cf76146102ad57806346eb65cb146102cd575b600080fd5b61027461026f36600461406c565b6105cd565b60405161028393929190614abe565b60405180910390f35b61029f61029a366004613b30565b610666565b604051610283929190614ca6565b6102c06102bb366004613b30565b610688565b604051610283919061499b565b6102e06102db36600461406c565b6106b0565b005b6102f56102f0366004613a4b565b610734565b60405161028391906148f3565b610315610310366004613a2f565b6107b7565b6040516102839190614b1e565b610315610330366004613b74565b610866565b61034861034336600461406c565b610919565b6040516102839493929190614bb2565b61036b61036636600461406c565b6109b9565b60405161028394939291906149dc565b61038e610389366004614242565b610a4b565b6040516102839190614b9f565b6102c06103a936600461434a565b610afd565b6102c06103bc366004613b30565b610b7e565b6103d46103cf36600461406c565b611474565b6040516102839291906149b9565b6103ea611507565b604051610283919061465f565b6103ea611516565b61041261040d36600461406c565b611525565b604051610283959493929190614a18565b6102c06104313660046142f1565b6115ca565b6102f5610444366004613bf6565b61164b565b61045c610457366004613cc4565b6116c4565b604051610283919061480c565b610315610477366004613bcb565b61177e565b61031561048a366004613a99565b61182e565b6104a261049d36600461406c565b6118e4565b60405161028393929190614ae9565b6102c0611974565b6103ea61197a565b6104d46104cf36600461406c565b611989565b6040516102839493929190614a7b565b6102f56104f2366004613a4b565b611a1b565b6102c0610505366004613b30565b611a89565b61038e610518366004614242565b612365565b61031561052b366004613d9f565b6123c7565b61054361053e36600461406c565b61241c565b60405161028391906149a4565b61056361055e366004613d48565b6124bf565b60405161028393929190614858565b610585610580366004613a4b565b6125f7565b604051610283929190614976565b6105a66105a136600461429a565b612610565b60405161028393929190614c4a565b6103ea612980565b6103ea61298f565b6103ea61299e565b600080600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a856040518263ffffffff1660e01b81526004016106099190614b1e565b60606040518083038186803b15801561062157600080fd5b505af4158015610635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106599190810190613fc2565b9250925092509193909250565b6000806106738484610b7e565b915061067f8484611a89565b90509250929050565b60008060006106978585610666565b915091506106a582826129ad565b925050505b92915050565b6040517f46eb65cb00000000000000000000000000000000000000000000000000000000815273__$d8b635de2bf4a097b4e18b67d0fb68e779$__906346eb65cb90610700908490600401614b1e565b60006040518083038186803b15801561071857600080fd5b505af415801561072c573d6000803e3d6000fd5b505050505b50565b606060008251905080604051908082528060200260200182016040528015610766578160200160208202803883390190505b50915060005b8181146107af576107908585838151811061078357fe5b6020026020010151611a89565b83828151811061079c57fe5b602090810291909101015260010161076c565b505092915050565b6040517f590aa87500000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063590aa8759061080a90859060040161465f565b60006040518083038186803b15801561082257600080fd5b505af4158015610836573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085e919081019061409f565b90505b919050565b6040517f63eb399200000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__906363eb3992906108bd9087908790879060040161478c565b60006040518083038186803b1580156108d557600080fd5b505af41580156108e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610911919081019061409f565b949350505050565b60608060608073__$fddee3b26a806429350031cf3481976d2e$__636f83188e866040518263ffffffff1660e01b81526004016109569190614b1e565b60006040518083038186803b15801561096e57600080fd5b505af4158015610982573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa919081019061410d565b93509350935093509193509193565b6000806000606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016109f79190614b1e565b60006040518083038186803b158015610a0f57600080fd5b505af4158015610a23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613e46565b600080546040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91639caa023b91610aad916001600160a01b0316908890889088906004016147be565b60206040518083038186803b158015610ac557600080fd5b505af4158015610ad9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061091191908101906140ee565b600061091184610b796040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612a1a565b600080610b91838263ffffffff612a2e16565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610bec576000610bd884601063ffffffff612a6716565b9050610be48186612a9a565b92505061146d565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415610e055760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401610c589190614b1e565b60606040518083038186803b158015610c7057600080fd5b505af4158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ca89190810190613fc2565b6040519194509250606091507f6352211e0000000000000000000000000000000000000000000000000000000090610ce490849060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051610d5f9190614643565b600060405180830381855afa9150503d8060008114610d9a576040519150601f19603f3d011682016040523d82523d6000602084013e610d9f565b606091505b50915091506000828015610db4575081516020145b610dbf576000610dd0565b610dd082600c63ffffffff612a6716565b9050896001600160a01b0316816001600160a01b031614610df2576000610df5565b60015b60ff16975050505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156110a157600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b8152600401610e739190614b1e565b60006040518083038186803b158015610e8b57600080fd5b505af4158015610e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ec79190810190613eb0565b5081519296509094509250905060005b81811461109757828181518110610eea57fe5b602002602001015160001415610eff5761108f565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b90879085908110610f3357fe5b6020026020010151604051602401610f4c9291906147f3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060876001600160a01b031683604051610fc79190614643565b600060405180830381855afa9150503d8060008114611002576040519150601f19603f3d011682016040523d82523d6000602084013e611007565b606091505b5091509150600082801561101c575081516020145b611027576000611038565b61103882600063ffffffff612b9216565b9050600087868151811061104857fe5b6020026020010151828161105857fe5b049050806110745760009b5050505050505050505050506106aa565b8b81108061108057508b155b1561108957809b505b50505050505b600101610ed7565b505050505061146d565b6001600160e01b031981167fc339d10a0000000000000000000000000000000000000000000000000000000014156111d4576040516060907fa85e59e4000000000000000000000000000000000000000000000000000000009061111090869060009081908190602401614b31565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199094169390931790925260045491519092506000916001600160a01b031690611177908490614643565b600060405180830381855afa9150503d80600081146111b2576040519150601f19603f3d011682016040523d82523d6000602084013e6111b7565b606091505b50509050806111c75760006111cb565b6000195b9350505061146d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156112fd5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016112409190614b1e565b60006040518083038186803b15801561125857600080fd5b505af415801561126c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112949190810190613e46565b5092509250506112a2612b9e565b6001600160a01b0316826001600160a01b03161480156112cf57506005546001600160a01b038281169116145b156112f65760006112e76112e1612bb6565b88612a9a565b90506112f281612bce565b9450505b505061146d565b6001600160e01b031981167f94cfcdd700000000000000000000000000000000000000000000000000000000141561146d5760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b81526004016113699190614b1e565b60006040518083038186803b15801561138157600080fd5b505af4158015611395573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113bd9190810190614002565b80519194509250905060005b818114611468578381815181106113dc57fe5b6020026020010151600014156113f157611460565b60006114108985848151811061140357fe5b6020026020010151610b7e565b9050600085838151811061142057fe5b6020026020010151828161143057fe5b049050806114485760009750505050505050506106aa565b87811080611454575087155b1561145d578097505b50505b6001016113c9565b505050505b5092915050565b60008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__638f4ce479846040518263ffffffff1660e01b81526004016114ae9190614b1e565b604080518083038186803b1580156114c557600080fd5b505af41580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114fd9190810190613e0f565b915091505b915091565b6004546001600160a01b031681565b6000546001600160a01b031681565b600080606080606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b81526004016115649190614b1e565b60006040518083038186803b15801561157c57600080fd5b505af4158015611590573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115b89190810190613eb0565b939a9299509097509550909350915050565b6000610911846116466040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612dcc565b6060808251604051908082528060200260200182016040528015611679578160200160208202803883390190505b50905060005b8351811461146d5783818151811061169357fe5b60200260200101516001600160a01b0316318282815181106116b157fe5b602090810291909101015260010161167f565b6000546040517f02cffc4500000000000000000000000000000000000000000000000000000000815260609173__$7a69f714cdde1cb6b62e3c39bc8c94deae$__916302cffc459161172a916001600160a01b039091169088908890889060040161468d565b60006040518083038186803b15801561174257600080fd5b505af4158015611756573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109119190810190613c29565b6040517fa6627e9f00000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063a6627e9f906117d390869086906004016147f3565b60006040518083038186803b1580156117eb57600080fd5b505af41580156117ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611827919081019061409f565b9392505050565b6040517fb43cffe100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063b43cffe190611887908890889088908890600401614746565b60006040518083038186803b15801561189f57600080fd5b505af41580156118b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118db919081019061409f565b95945050505050565b600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6856040518263ffffffff1660e01b81526004016119209190614b1e565b60006040518083038186803b15801561193857600080fd5b505af415801561194c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106599190810190614002565b60065481565b6005546001600160a01b031681565b6000806060600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63ca49f47c866040518263ffffffff1660e01b81526004016119c79190614b1e565b60006040518083038186803b1580156119df57600080fd5b505af41580156119f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613f5a565b606060008251905080604051908082528060200260200182016040528015611a4d578160200160208202803883390190505b50915060005b8181146107af57611a6a8585838151811061140357fe5b838281518110611a7657fe5b6020908102919091010152600101611a53565b600080611a9c838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd7000000000000000000000000000000000000000000000000000000001415611c075760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b8152600401611b0a9190614b1e565b60006040518083038186803b158015611b2257600080fd5b505af4158015611b36573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b5e9190810190614002565b80519194509250905060005b818114611bfc57838181518110611b7d57fe5b602002602001015160001415611b9257611bf4565b6000611ba48985848151811061078357fe5b90506000858381518110611bb457fe5b60200260200101518281611bc457fe5b04905080611bdc5760009750505050505050506106aa565b87811080611be8575087155b15611bf1578097505b50505b600101611b6a565b506106aa9350505050565b6001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415611c68576000611c4c84601063ffffffff612a6716565b600154909150610be490829087906001600160a01b0316612ddb565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415611fb85760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401611cd49190614b1e565b60606040518083038186803b158015611cec57600080fd5b505af4158015611d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d249190810190613fc2565b600254604051929550909350606092507fe985e9c50000000000000000000000000000000000000000000000000000000091611d70918a916001600160a01b0390911690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051611deb9190614643565b600060405180830381855afa9150503d8060008114611e26576040519150601f19603f3d011682016040523d82523d6000602084013e611e2b565b606091505b5091509150811580611e3f57508051602014155b80611e5b5750611e5681600063ffffffff612b9216565b600114155b15611fa9576040516060907f081812fc0000000000000000000000000000000000000000000000000000000090611e9690879060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050856001600160a01b031681604051611f0d9190614643565b600060405180830381855afa9150503d8060008114611f48576040519150601f19603f3d011682016040523d82523d6000602084013e611f4d565b606091505b509093509150828015611f61575081516020145b8015611f9057506002546001600160a01b0316611f8583600c63ffffffff612a6716565b6001600160a01b0316145b611f9b576000611f9e565b60015b60ff16975050611097565b6000199650505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156121df576040517f9eadc83500000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__90639eadc8359061203d908790600401614b1e565b60006040518083038186803b15801561205557600080fd5b505af4158015612069573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120919190810190613eb0565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926120db925089916001600160a01b031690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060836001600160a01b0316836040516121569190614643565b600060405180830381855afa9150503d8060008114612191576040519150601f19603f3d011682016040523d82523d6000602084013e612196565b606091505b50915091508180156121a9575080516020145b80156121c557506121c181600063ffffffff612b9216565b6001145b6121d05760006121d4565b6000195b95505050505061146d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561221b57600019915061146d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561146d5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016122879190614b1e565b60006040518083038186803b15801561229f57600080fd5b505af41580156122b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122db9190810190613e46565b5092509250506122e9612b9e565b6001600160a01b0316826001600160a01b031614801561231657506005546001600160a01b038281169116145b1561235c57600061233b612328612bb6565b60055489906001600160a01b0316612ddb565b905060001981146123545761234f81612bce565b612358565b6000195b9450505b50505092915050565b600080546040517f8dccde0400000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91638dccde0491610aad916001600160a01b0316908890889088906004016147be565b6040517fd3d862d100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d3d862d1906117d39086908690600401614906565b6040517fd469502800000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d46950289061246f908590600401614b1e565b60206040518083038186803b15801561248757600080fd5b505af415801561249b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061085e9190810190613df4565b60608060606000855190508060405190808252806020026020018201604052801561250457816020015b6124f1613467565b8152602001906001900390816124e95790505b50935080604051908082528060200260200182016040528015612531578160200160208202803883390190505b5092508060405190808252806020026020018201604052801561255e578160200160208202803883390190505b50915060005b8181146125ee5761259b87828151811061257a57fe5b602002602001015187838151811061258e57fe5b6020026020010151612610565b87518890859081106125a957fe5b602002602001018785815181106125bc57fe5b602002602001018786815181106125cf57fe5b9315156020948502919091019093019290925291905252600101612564565b50509250925092565b6060806126048484611a1b565b915061067f8484610734565b612618613467565b600080546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815282916001600160a01b031690639d3fa4b990612662908890600401614c6e565b60606040518083038186803b15801561267a57600080fd5b505afa15801561268e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126b291908101906141fa565b85516000546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f906127049089908990600401614c81565b60206040518083038186803b15801561271c57600080fd5b505afa158015612730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127549190810190613dd4565b9150600061276187612ee5565b90506000612782886101800151896101400151612f0190919063ffffffff16565b156127b7576127b0826127a68a60c001518b60800151612f2690919063ffffffff16565b8a60a00151612f42565b9050612824565b60c08801516127d3576127b08289608001518a60a00151612f42565b60006127e4848a6101800151610688565b905060006127fb848b608001518c60a00151612f42565b90506000612812838c60c001518d60a00151612f42565b905061281e82826129ad565b93505050505b61284861284287604001518a60a00151612f6490919063ffffffff16565b826129ad565b9450600460005460208a01516040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__92639caa023b926128b3926001600160a01b03909216918e91908c906004016147be565b60206040518083038186803b1580156128cb57600080fd5b505af41580156128df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061290391908101906140ee565b600481111561290e57fe5b1461291a57600061291c565b845b945061292c886101600151612f83565b61293557600094505b60e0880151158015906129535750612951886101a00151612f83565b155b1561295d57600094505b60038651600681111561296c57fe5b1461297657600094505b5050509250925092565b6001546001600160a01b031681565b6002546001600160a01b031681565b6003546001600160a01b031681565b60008183106129bc5781611827565b5090919050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b600061182782612a2985613138565b6131b3565b60008160040183511015612a5457612a54612a4f60038551856004016131ed565b61325c565b5001602001516001600160e01b03191690565b60008160140183511015612a8857612a88612a4f60048551856014016131ed565b5001601401516001600160a01b031690565b60405160009081906060906001600160a01b038616907f70a082310000000000000000000000000000000000000000000000000000000090612ae090879060240161465f565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612b339190614643565b600060405180830381855afa9150503d8060008114612b6e576040519150601f19603f3d011682016040523d82523d6000602084013e612b73565b606091505b5091509150818015612b86575080516020145b156107af576106a58160005b60006118278383613264565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b600080612bd9612bb6565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c1357600080fd5b505af1158015612c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c4b91908101906140d2565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c8a57600080fd5b505af1158015612c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cc29190810190614402565b4211612d4057816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d0357600080fd5b505af1158015612d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d3b9190810190614402565b612db3565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d7b57600080fd5b505af1158015612d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612db39190810190614402565b9050610911816b033b2e3c9fd0803ce800000086612f42565b600061182782612a298561328e565b60405160009081906060906001600160a01b038716907fdd62ed3e0000000000000000000000000000000000000000000000000000000090612e239088908890602401614673565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612e769190614643565b600060405180830381855afa9150503d8060008114612eb1576040519150601f19603f3d011682016040523d82523d6000602084013e612eb6565b606091505b5091509150818015612ec9575080516020145b15612edc57612ed9816000612b92565b92505b50509392505050565b6000806000612ef384613347565b9150915061091182826129ad565b6000815183511480156118275750508051602091820120825192909101919091201490565b60008282018381101561182757611827612a4f6000868661338a565b600061091183612f58868563ffffffff6133a916565b9063ffffffff6133da16565b600082821115612f7d57612f7d612a4f6002858561338a565b50900390565b60006020825181612f9057fe5b06600414612fa057506000610861565b6000612fb2838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd70000000000000000000000000000000000000000000000000000000014612fef576001915050610861565b6040517fbbb2dcf600000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063bbb2dcf690613042908790600401614b1e565b60006040518083038186803b15801561305a57600080fd5b505af415801561306e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130969190810190614002565b80519093509150600090505b81811461312c5760006130d260008584815181106130bc57fe5b6020026020010151612a2e90919063ffffffff16565b90506001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415613123576131108483613404565b1561312357600095505050505050610861565b506001016130a2565b50600195945050505050565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060632800659560e01b84848460405160240161320c93929190614b91565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b6000816020018351101561328557613285612a4f60058551856020016131ed565b50016020015190565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a7534939092909160208710156132da57fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b600080600483610140015151101561336457506000905080611502565b6133778360000151846101400151610b7e565b6114fd8460000151856101400151611a89565b606063e946c1bb60e01b84848460405160240161320c93929190614b6f565b6000826133b8575060006106aa565b828202828482816133c557fe5b041461182757611827612a4f6001868661338a565b6000816133f0576133f0612a4f6003858561338a565b60008284816133fb57fe5b04949350505050565b8151600090600183015b818110156107af5761344f85828151811061342557fe5b602002602001015186868151811061343957fe5b6020026020010151612f0190919063ffffffff16565b1561345f576001925050506106aa565b60010161340e565b6040805160608101909152806000815260006020820181905260409091015290565b80356106aa81614d59565b80516106aa81614d59565b600082601f8301126134af578081fd5b81356134c26134bd82614cdb565b614cb4565b8181529150602080830190848101818402860182018710156134e357600080fd5b60005b848110156114685781356134f981614d59565b845292820192908201906001016134e6565b600082601f83011261351b578081fd5b81356135296134bd82614cdb565b8181529150602080830190840160005b838110156135665761355187602084358901016136fa565b83526020928301929190910190600101613539565b5050505092915050565b600082601f830112613580578081fd5b815161358e6134bd82614cdb565b8181529150602080830190840160005b83811015613566576135b68760208451890101613748565b8352602092830192919091019060010161359e565b600082601f8301126135db578081fd5b81356135e96134bd82614cdb565b8181529150602080830190840160005b8381101561356657613611876020843589010161379d565b835260209283019291909101906001016135f9565b600082601f830112613636578081fd5b81356136446134bd82614cdb565b81815291506020808301908481018184028601820187101561366557600080fd5b60005b8481101561146857813584529282019290820190600101613668565b600082601f830112613694578081fd5b81516136a26134bd82614cdb565b8181529150602080830190848101818402860182018710156136c357600080fd5b60005b84811015611468578151845292820192908201906001016136c6565b80516001600160e01b0319811681146106aa57600080fd5b600082601f83011261370a578081fd5b81356137186134bd82614cfb565b915080825283602082850101111561372f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112613758578081fd5b81516137666134bd82614cfb565b915080825283602082850101111561377d57600080fd5b61146d816020840160208601614d1f565b8051600581106106aa57600080fd5b60006101c08083850312156137b0578182fd5b6137b981614cb4565b9150506137c68383613489565b81526137d58360208401613489565b60208201526137e78360408401613489565b60408201526137f98360608401613489565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561385b57600080fd5b613867868387016136fa565b8385015261016092508285013591508082111561388357600080fd5b61388f868387016136fa565b838501526101809250828501359150808211156138ab57600080fd5b6138b7868387016136fa565b838501526101a09250828501359150808211156138d357600080fd5b506138e0858286016136fa565b82840152505092915050565b60006101c08083850312156138ff578182fd5b61390881614cb4565b9150506139158383613494565b81526139248360208401613494565b60208201526139368360408401613494565b60408201526139488360608401613494565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156139aa57600080fd5b6139b686838701613748565b838501526101609250828501519150808211156139d257600080fd5b6139de86838701613748565b838501526101809250828501519150808211156139fa57600080fd5b613a0686838701613748565b838501526101a0925082850151915080821115613a2257600080fd5b506138e085828601613748565b600060208284031215613a40578081fd5b813561182781614d59565b60008060408385031215613a5d578081fd5b8235613a6881614d59565b9150602083013567ffffffffffffffff811115613a83578182fd5b613a8f8582860161350b565b9150509250929050565b60008060008060808587031215613aae578182fd5b8435613ab981614d59565b9350602085013567ffffffffffffffff80821115613ad5578384fd5b613ae188838901613626565b94506040870135915080821115613af6578384fd5b613b0288838901613626565b93506060870135915080821115613b17578283fd5b50613b24878288016136fa565b91505092959194509250565b60008060408385031215613b42578182fd5b8235613b4d81614d59565b9150602083013567ffffffffffffffff811115613b68578182fd5b613a8f858286016136fa565b600080600060608486031215613b88578081fd5b8335613b9381614d59565b9250602084013567ffffffffffffffff811115613bae578182fd5b613bba868287016136fa565b925050604084013590509250925092565b60008060408385031215613bdd578182fd5b8235613be881614d59565b946020939093013593505050565b600060208284031215613c07578081fd5b813567ffffffffffffffff811115613c1d578182fd5b6109118482850161349f565b60006020808385031215613c3b578182fd5b825167ffffffffffffffff811115613c51578283fd5b80840185601f820112613c62578384fd5b80519150613c726134bd83614cdb565b8281528381019082850185850284018601891015613c8e578687fd5b8693505b84841015613cb857613ca4898261378e565b835260019390930192918501918501613c92565b50979650505050505050565b600080600060608486031215613cd8578081fd5b833567ffffffffffffffff80821115613cef578283fd5b613cfb878388016135cb565b94506020860135915080821115613d10578283fd5b613d1c8783880161349f565b93506040860135915080821115613d31578283fd5b50613d3e86828701613626565b9150509250925092565b60008060408385031215613d5a578182fd5b823567ffffffffffffffff80821115613d71578384fd5b613d7d868387016135cb565b93506020850135915080821115613d92578283fd5b50613a8f8582860161350b565b60008060408385031215613db1578182fd5b823567ffffffffffffffff80821115613dc8578384fd5b613d7d86838701613626565b600060208284031215613de5578081fd5b81518015158114611827578182fd5b600060208284031215613e05578081fd5b61182783836136e2565b60008060408385031215613e21578182fd5b613e2b84846136e2565b91506020830151613e3b81614d59565b809150509250929050565b60008060008060808587031215613e5b578182fd5b8451613e6681614d6e565b6020860151909450613e7781614d59565b6040860151909350613e8881614d59565b606086015190925067ffffffffffffffff811115613ea4578182fd5b613b2487828801613748565b600080600080600060a08688031215613ec7578283fd5b613ed187876136e2565b94506020860151613ee181614d59565b604087015190945067ffffffffffffffff80821115613efe578485fd5b613f0a89838a01613684565b94506060880151915080821115613f1f578283fd5b613f2b89838a01613684565b93506080880151915080821115613f40578283fd5b50613f4d88828901613748565b9150509295509295909350565b60008060008060808587031215613f6f578182fd5b613f7986866136e2565b93506020850151613f8981614d59565b604086015190935067ffffffffffffffff811115613fa5578283fd5b613fb187828801613748565b606096909601519497939650505050565b600080600060608486031215613fd6578081fd5b613fe085856136e2565b92506020840151613ff081614d59565b80925050604084015190509250925092565b600080600060608486031215614016578081fd5b835161402181614d6e565b602085015190935067ffffffffffffffff8082111561403e578283fd5b61404a87838801613684565b9350604086015191508082111561405f578283fd5b50613d3e86828701613570565b60006020828403121561407d578081fd5b813567ffffffffffffffff811115614093578182fd5b610911848285016136fa565b6000602082840312156140b0578081fd5b815167ffffffffffffffff8111156140c6578182fd5b61091184828501613748565b6000602082840312156140e3578081fd5b815161182781614d59565b6000602082840312156140ff578081fd5b815160058110611827578182fd5b60008060008060808587031215614122578182fd5b845167ffffffffffffffff80821115614139578384fd5b61414588838901613748565b955060209150818701518181111561415b578485fd5b80880189601f82011261416c578586fd5b8051915061417c6134bd83614cdb565b82815284810190828601885b858110156141b15761419f8e8984518801016138ec565b84529287019290870190600101614188565b505060408b01519098509450505050808211156141cc578384fd5b6141d888838901613684565b935060608701519150808211156141ed578283fd5b50613b2487828801613570565b60006060828403121561420b578081fd5b6142156060614cb4565b825160078110614223578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614256578081fd5b833567ffffffffffffffff81111561426c578182fd5b6142788682870161379d565b935050602084013561428981614d59565b929592945050506040919091013590565b600080604083850312156142ac578182fd5b823567ffffffffffffffff808211156142c3578384fd5b6142cf8683870161379d565b935060208501359150808211156142e4578283fd5b50613a8f858286016136fa565b600080600060608486031215614305578081fd5b833567ffffffffffffffff81111561431b578182fd5b6143278682870161379d565b93505060208401359150604084013561433f81614d59565b809150509250925092565b60008060006060848603121561435e578081fd5b833567ffffffffffffffff80821115614375578283fd5b81860160a08189031215614387578384fd5b61439160a0614cb4565b92508035835260208101356020840152604081013560408401526143b88860608301613489565b60608401526080810135828111156143ce578485fd5b6143da898284016136fa565b6080850152509194505050602084013591506143f98560408601613489565b90509250925092565b600060208284031215614413578081fd5b5051919050565b6001600160a01b03169052565b6000815180845260208401935060208301825b828110156144615781516001600160a01b031686526020958601959091019060010161443a565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b848110156144b65782840388526144a08483516144f3565b6020988901989094509190910190600101614488565b50919695505050505050565b6000815180845260208401935060208301825b828110156144615781518652602095860195909101906001016144d5565b6000815180845261450b816020860160208601614d1f565b601f01601f19169290920160200192915050565b80516007811061452b57fe5b825260208181015190830152604090810151910152565b60006101c061455284845161441a565b6020830151614564602086018261441a565b506040830151614577604086018261441a565b50606083015161458a606086018261441a565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e08501526101008084015181860152506101208084015181860152506101408084015182828701526145e3838701826144f3565b9150506101609150818401518582038387015261460082826144f3565b92505050610180808401518583038287015261461c83826144f3565b9150506101a09150818401518582038387015261463982826144f3565b9695505050505050565b60008251614655818460208701614d1f565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6000608082016001600160a01b03871683526080602084015280865180835260a08501915060a060208202860101925060208801845b82811015614712577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608786030184526146fd858351614542565b945060209384019391909101906001016146c3565b5050505082810360408401526147288186614427565b838103606085015261473a81866144c2565b98975050505050505050565b60006001600160a01b03861682526080602083015261476860808301866144c2565b828103604084015261477a81866144c2565b838103606085015261473a81866144f3565b60006001600160a01b0385168252606060208301526147ae60608301856144f3565b9050826040830152949350505050565b60006001600160a01b038087168352608060208401526147e16080840187614542565b94166040830152506060015292915050565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000918401906040840190835b8181101561484d57835161483981614d4f565b835260209384019390920191600101614826565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561489b5761488884835161451f565b6060939093019290840190600101614875565b505050838103828501526148af81876144c2565b84810360408601528551808252908301915082860190845b818110156148e55782511515845292840192918401916001016148c7565b509198975050505050505050565b60006020825261182760208301846144c2565b60006040825261491960408301856144c2565b602083820381850152818551808452828401915082838202850101838801865b8381101561496757601f198784030185526149558383516144f3565b94860194925090850190600101614939565b50909998505050505050505050565b60006040825261498960408301856144c2565b82810360208401526118db81856144c2565b90815260200190565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261463960808301846144f3565b60006001600160e01b0319871682526001600160a01b038616602083015260a06040830152614a4a60a08301866144c2565b8281036060840152614a5c81866144c2565b8381036080850152614a6e81866144f3565b9998505050505050505050565b60006001600160e01b0319861682526001600160a01b038516602083015260806040830152614aad60808301856144f3565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b03198516825260606020830152614b0c60608301856144c2565b8281036040840152614639818561446b565b60006020825261182760208301846144f3565b600060808252614b4460808301876144f3565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6060810160048510614b7d57fe5b938152602081019290925260409091015290565b6060810160088510614b7d57fe5b60208101614bac83614d4f565b91905290565b600060808252614bc560808301876144f3565b602083820381850152818751808452828401915082838202850101838a01865b83811015614c1357601f19878403018552614c01838351614542565b94860194925090850190600101614be5565b50508681036040880152614c27818a6144c2565b9450505050508281036060840152614c3f818561446b565b979650505050505050565b60a08101614c58828661451f565b8360608301528215156080830152949350505050565b6000602082526118276020830184614542565b600060408252614c946040830185614542565b82810360208401526118db81856144f3565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715614cd357600080fd5b604052919050565b600067ffffffffffffffff821115614cf1578081fd5b5060209081020190565b600067ffffffffffffffff821115614d11578081fd5b50601f01601f191660200190565b60005b83811015614d3a578181015183820152602001614d22565b83811115614d49576000848401525b50505050565b6005811061073157fe5b6001600160a01b038116811461073157600080fd5b6001600160e01b03198116811461073157600080fdfea365627a7a7231582034aeeb2766e909a7bf6404cf5556e26fa49952bdd5ea533d25447be58f55ed9a6c6578706572696d656e74616cf564736f6c63430005100040" }, "deployedBytecode": { - "object": "0x608060405234801561001057600080fd5b50600436106102f45760003560e01c80639a7e752611610191578063ca49f47c116100e3578063d3d862d111610097578063e4e6e7da11610071578063e4e6e7da1461077e578063e77286eb1461079f578063ee4f5a94146107c1576102f4565b8063d3d862d114610729578063d46950281461073c578063e25cabf71461075c576102f4565b8063d001c5dc116100c8578063d001c5dc146106f0578063d186037f14610703578063d363790514610716576102f4565b8063ca49f47c146106ac578063cafd3a07146106cf576102f4565b8063a6627e9f11610145578063bbb2dcf61161011f578063bbb2dcf614610661578063bc03f96414610683578063c26cfecd146106a4576102f4565b8063a6627e9f14610618578063acaedc741461062b578063b43cffe11461064e576102f4565b8063a070cac811610176578063a070cac8146105d2578063a0901e51146105e5578063a5cd62ba146105f8576102f4565b80639a7e75261461058b5780639eadc835146105ae576102f4565b80634dfdac201161024a5780637914b2ec116101fe5780637b66ad34116101d85780637b66ad34146105445780637d727512146105655780638f4ce47914610578576102f4565b80637914b2ec146104f05780637982653e1461051157806379c9c42614610531576102f4565b806363eb39921161022f57806363eb39921461049857806365129042146104ab578063750bdb30146104cd576102f4565b80634dfdac2014610458578063590aa87514610478576102f4565b8063314853ff116102ac5780633db6dc61116102865780633db6dc61146103ff578063459be5e21461042257806346eb65cb14610443576102f4565b8063314853ff146103a8578063327d3054146103ca57806332aae3ad146103dd576102f4565b80630d7b7d76116102dd5780630d7b7d7614610345578063165979e1146103665780632322cf7614610388576102f4565b806302d0aec3146102f957806304a5618a14610323575b600080fd5b61030c610307366004614a21565b6107e3565b60405161031a92919061535e565b60405180910390f35b610336610331366004614a21565b61083f565b60405161031a93929190615488565b610358610353366004614603565b6108ba565b60405161031a92919061530c565b610379610374366004614a21565b6108dc565b60405161031a939291906155c3565b61039b610396366004614603565b610939565b60405161031a91906152c9565b6103bb6103b6366004614a21565b610961565b60405161031a93929190615333565b6103586103d8366004614a21565b6109a8565b6103f06103eb366004614a21565b6109ea565b60405161031a93929190615539565b61041261040d366004614a21565b610a3d565b60405161031a94939291906152d2565b610435610430366004614a21565b610a87565b60405161031a9291906155ac565b610456610451366004614a21565b610add565b005b61046b61046636600461452a565b610c5f565b60405161031a9190615263565b61048b610486366004614341565b610ce2565b60405161031a91906154e8565b61048b6104a6366004614647565b610d52565b6104be6104b9366004614a21565b610dc8565b60405161031a9392919061502f565b6104e06104db366004614a21565b610e02565b60405161031a94939291906153b3565b6105036104fe366004614a21565b610e99565b60405161031a929190615390565b61052461051f366004614ab8565b610ed1565b60405161031a91906155de565b61039b61053f366004614bc0565b61118c565b610557610552366004614a21565b611215565b60405161031a929190615015565b61039b610573366004614603565b61124d565b610503610586366004614a21565b6118a4565b61059e610599366004614a21565b61191a565b60405161031a94939291906155f2565b6105c16105bc366004614a21565b61197b565b60405161031a9594939291906153ef565b61039b6105e0366004614b67565b611a0c565b61046b6105f33660046146c9565b611a8d565b61060b6106063660046146fc565b611b06565b60405161031a919061517b565b61048b61062636600461469e565b611bc9565b61063e610639366004614a21565b611c22565b60405161031a94939291906150d7565b61048b61065c366004614578565b611c5e565b61067461066f366004614a21565b611cd6565b60405161031a939291906154b3565b610696610691366004614a21565b611d50565b60405161031a92919061531a565b61039b611d89565b6106bf6106ba366004614a21565b611d8f565b60405161031a9493929190615445565b6106e26106dd366004614a21565b611e19565b60405161031a929190615629565b61046b6106fe36600461452a565b611e67565b61039b610711366004614603565b611ed5565b610524610724366004614ab8565b6126c7565b61048b6107373660046147cd565b612a77565b61074f61074a366004614a21565b612a96565b60405161031a919061537b565b61076f61076a366004614776565b612b91565b60405161031a939291906151c8565b61079161078c36600461452a565b612cc9565b60405161031a9291906152a4565b6107b26107ad366004614b10565b612ce2565b60405161031a939291906156db565b6107d46107cf366004614a21565b612fa4565b60405161031a93929190615582565b6000806107f7836107f2612fe1565b613005565b600061081060048551866130459092919063ffffffff16565b80602001905161082391908101906149d4565b909350905060ff8116600681111561083757fe5b915050915091565b60008080610853848263ffffffff61308816565b92506001600160e01b0319831663012b8bc960e11b1461088e5760405162461bcd60e51b8152600401610885906156a4565b60405180910390fd5b61089f84601063ffffffff6130bc16565b91506108b284602463ffffffff6130ef16565b929491935050565b6000806108c7848461124d565b91506108d38484611ed5565b90509250929050565b60008060006108ed846107f26130fb565b600061090660048651876130459092919063ffffffff16565b8060200190516109199190810190614d92565b9094509250905060ff8116600281111561092f57fe5b9350509193909250565b600080600061094885856108ba565b91509150610956828261311f565b925050505b92915050565b6000606080610972846107f2613135565b835161098890859060049063ffffffff61304516565b80602001905161099b9190810190614974565b9196909550909350915050565b6000806109b7836107f2613159565b82516109cd90849060049063ffffffff61304516565b8060200190516109e09190810190614916565b9094909350915050565b60008060606109fb846107f261317d565b6000610a1460048651876130459092919063ffffffff16565b806020019051610a279190810190614d52565b9094509250905060ff8116600181111561092f57fe5b600080606080610a4f856107f26131a1565b8451610a6590869060049063ffffffff61304516565b806020019051610a7891908101906148d2565b92989197509550909350915050565b600080610a96836107f26131c5565b6000610aaf60048551866130459092919063ffffffff16565b806020019051610ac29190810190614c90565b9250905060ff81166003811115610ad557fe5b925050915091565b6000610aef828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610b3357610b2c826118a4565b5050610c5b565b6001600160e01b0319811663012b8bc960e11b1415610b5d57610b558261083f565b505050610c5b565b6001600160e01b031981167fa7cb5fb7000000000000000000000000000000000000000000000000000000001415610ba257610b988261197b565b5050505050610c5b565b6001600160e01b031981166394cfcdd760e01b1415610bc457610b5582611cd6565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415610c0857610bff82611d8f565b50505050610c5b565b6001600160e01b031981167fdc1600f3000000000000000000000000000000000000000000000000000000001415610c4357610bff82610e02565b60405162461bcd60e51b8152600401610885906156a4565b5050565b606060008251905080604051908082528060200260200182016040528015610c91578160200160208202803883390190505b50915060005b818114610cda57610cbb85858381518110610cae57fe5b6020026020010151611ed5565b838281518110610cc757fe5b6020908102919091010152600101610c97565b505092915050565b6040516060907ff47261b00000000000000000000000000000000000000000000000000000000090610d18908490602401615001565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b919050565b6040516060907fc339d10a0000000000000000000000000000000000000000000000000000000090610d8c908690869086906024016150a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b9392505050565b6000806000610dd9846107f26131e9565b8351610def90859060049063ffffffff61304516565b80602001905161099b91908101906143f8565b600080806060610e18858363ffffffff61308816565b93506001600160e01b031984167fdc1600f30000000000000000000000000000000000000000000000000000000014610e635760405162461bcd60e51b8152600401610885906156a4565b8451610e7990869060049063ffffffff61320d16565b806020019051610e8c9190810190614396565b9597919650949350915050565b600080610ea8836107f261328d565b8251610ebe90849060049063ffffffff61304516565b8060200190516109e091908101906149f8565b6000610edb613f0c565b610f6c8584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b505afa158015610f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f669190810190614c78565b3a6132b1565b60408051600280825260608281019093529293509091816020015b6060815260200190600190039081610f8757505060408051600280825260608083018452939450909160208301908038833950506040805160028082526060808301845294955090925090602083019080388339505060408051600280825260608083018452949550909250906020830190803883390190505090508861014001518460008151811061101657fe5b602002602001018190525088600001518360008151811061103357fe5b6001600160a01b039283166020918202929092010152881615611056578761106c565b73377f698c4c287018d09b516f415317aec59193325b8260008151811061107957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460000151816000815181106110ab57fe5b602002602001018181525050886101800151846001815181106110ca57fe5b60200260200101819052508860000151836001815181106110e757fe5b6001600160a01b03928316602091820292909201015260408a01511615611112578860400151611128565b73377f698c4c287018d09b516f415317aec59193325b8260018151811061113557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160018151811061116757fe5b60200260200101818152505061117f84848484613328565b9998505050505050505050565b600061120d846112086040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b61353d565b949350505050565b600080611224836107f2613551565b825161123a90849060049063ffffffff61304516565b8060200190516109e0919081019061435d565b600080611260838263ffffffff61308816565b90506001600160e01b031981167ff47261b00000000000000000000000000000000000000000000000000000000014156112bb5760006112a784601063ffffffff6130bc16565b90506112b38186613575565b92505061189d565b6001600160e01b0319811663012b8bc960e11b1415611413576000806112e08561083f565b6040519194509250606091507f6352211e000000000000000000000000000000000000000000000000000000009061131c9084906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b03168360405161136d9190614fe5565b600060405180830381855afa9150503d80600081146113a8576040519150601f19603f3d011682016040523d82523d6000602084013e6113ad565b606091505b509150915060008280156113c2575081516020145b6113cd5760006113de565b6113de82600c63ffffffff6130bc16565b9050896001600160a01b0316816001600160a01b031614611400576000611403565b60015b60ff16975050505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156116035760006060806114538661197b565b5081519296509094509250905060005b8181146115f95782818151811061147657fe5b60200260200101516000141561148b576115f1565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b908790859081106114bf57fe5b60200260200101516040516024016114d892919061510b565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060876001600160a01b0316836040516115299190614fe5565b600060405180830381855afa9150503d8060008114611564576040519150601f19603f3d011682016040523d82523d6000602084013e611569565b606091505b5091509150600082801561157e575081516020145b61158957600061159a565b61159a82600063ffffffff6130ef16565b905060008786815181106115aa57fe5b602002602001015182816115ba57fe5b049050806115d65760009b50505050505050505050505061095b565b8b8110806115e257508b155b156115eb57809b505b50505050505b600101611463565b505050505061189d565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415611721576040516060907fa85e59e40000000000000000000000000000000000000000000000000000000090611672908690600090819081906024016154fb565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260045491519092506000916001600160a01b0316906116c4908490614fe5565b600060405180830381855afa9150503d80600081146116ff576040519150601f19603f3d011682016040523d82523d6000602084013e611704565b606091505b5050905080611714576000611718565b6000195b9350505061189d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156117c85760008061175f85610e02565b50925092505061176d613678565b6001600160a01b0316826001600160a01b031614801561179a57506005546001600160a01b038281169116145b156117c15760006117b26117ac613690565b88613575565b90506117bd816136a8565b9450505b505061189d565b6001600160e01b031981166394cfcdd760e01b141561189d576060806117ed85611cd6565b80519194509250905060005b8181146118985783818151811061180c57fe5b60200260200101516000141561182157611890565b60006118408985848151811061183357fe5b602002602001015161124d565b9050600085838151811061185057fe5b6020026020010151828161186057fe5b0490508061187857600097505050505050505061095b565b87811080611884575087155b1561188d578097505b50505b6001016117f9565b505050505b5092915050565b6000806118b7838263ffffffff61308816565b91506001600160e01b031982167ff47261b000000000000000000000000000000000000000000000000000000000146119025760405162461bcd60e51b8152600401610885906156a4565b61191383601063ffffffff6130bc16565b9050915091565b6000806000606061192d856107f26138a6565b600061194660048751886130459092919063ffffffff16565b8060200190516119599190810190614cf4565b91965094509250905060ff8116600681111561197157fe5b9450509193509193565b60008060608080611992868563ffffffff61308816565b94506001600160e01b031985167fa7cb5fb700000000000000000000000000000000000000000000000000000000146119dd5760405162461bcd60e51b8152600401610885906156a4565b505050506024828101516044840151606485015160848601519496929591820184019490820184019391010190565b600061120d84611a886040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b6138ca565b6060808251604051908082528060200260200182016040528015611abb578160200160208202803883390190505b50905060005b8351811461189d57838181518110611ad557fe5b60200260200101516001600160a01b031631828281518110611af357fe5b6020908102919091010152600101611ac1565b606060008451905080604051908082528060200260200182016040528015611b38578160200160208202803883390190505b50915060005b818114611bc057611b89868281518110611b5457fe5b6020026020010151868381518110611b6857fe5b6020026020010151868481518110611b7c57fe5b60200260200101516126c7565b838281518110611b9557fe5b60200260200101906004811115611ba857fe5b90816004811115611bb557fe5b905250600101611b3e565b50509392505050565b60405160609063012b8bc960e11b90611be8908590859060240161510b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905092915050565b60006060806060611c35856107f26138d9565b8451611c4b90869060049063ffffffff61304516565b806020019051610a789190810190614492565b6040516060907fa7cb5fb70000000000000000000000000000000000000000000000000000000090611c9a908790879087908790602401615053565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050949350505050565b6000606080611ceb848463ffffffff61308816565b92506001600160e01b031983166394cfcdd760e01b14611d1d5760405162461bcd60e51b8152600401610885906156a4565b8351611d3390859060049063ffffffff61320d16565b806020019051611d469190810190614802565b9395909450915050565b60006060611d60836107f26138fd565b8251611d7690849060049063ffffffff61304516565b8060200190516109e09190810190614939565b60075481565b600080606081611da5858263ffffffff61308816565b93506001600160e01b031984167fc339d10a0000000000000000000000000000000000000000000000000000000014611df05760405162461bcd60e51b8152600401610885906156a4565b8451611e0690869060049063ffffffff61320d16565b806020019051610e8c919081019061443a565b600080611e28836107f2613921565b6000611e4160048551866130459092919063ffffffff16565b806020019051611e549190810190614c90565b9250905060ff81166001811115610ad557fe5b606060008251905080604051908082528060200260200182016040528015611e99578160200160208202803883390190505b50915060005b818114610cda57611eb68585838151811061183357fe5b838281518110611ec257fe5b6020908102919091010152600101611e9f565b600080611ee8838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b1415611fb857606080611f0f85611cd6565b80519194509250905060005b818114611fad57838181518110611f2e57fe5b602002602001015160001415611f4357611fa5565b6000611f5589858481518110610cae57fe5b90506000858381518110611f6557fe5b60200260200101518281611f7557fe5b04905080611f8d57600097505050505050505061095b565b87811080611f99575087155b15611fa2578097505b50505b600101611f1b565b5061095b9350505050565b6001600160e01b031981167ff47261b000000000000000000000000000000000000000000000000000000000141561210e576000611ffd84601063ffffffff6130bc16565b6001546040519192506060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916120439189916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b0316836040516120949190614fe5565b600060405180830381855afa9150503d80600081146120cf576040519150601f19603f3d011682016040523d82523d6000602084013e6120d4565b606091505b50915091508180156120e7575080516020145b6120f2576000612103565b61210381600063ffffffff6130ef16565b95505050505061189d565b6001600160e01b0319811663012b8bc960e11b1415612373576000806121338561083f565b600254604051929550909350606092507fe985e9c5000000000000000000000000000000000000000000000000000000009161217f918a916001600160a01b0390911690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b0316836040516121d09190614fe5565b600060405180830381855afa9150503d806000811461220b576040519150601f19603f3d011682016040523d82523d6000602084013e612210565b606091505b509150915081158061222457508051602014155b80612240575061223b81600063ffffffff6130ef16565b600114155b15612364576040516060907f081812fc000000000000000000000000000000000000000000000000000000009061227b9087906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050856001600160a01b0316816040516122c89190614fe5565b600060405180830381855afa9150503d8060008114612303576040519150601f19603f3d011682016040523d82523d6000602084013e612308565b606091505b50909350915082801561231c575081516020145b801561234b57506002546001600160a01b031661234083600c63ffffffff6130bc16565b6001600160a01b0316145b612356576000612359565b60015b60ff169750506115f9565b6000199650505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156124d35760006123b08461197b565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926123fa925089916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b03168360405161244b9190614fe5565b600060405180830381855afa9150503d8060008114612486576040519150601f19603f3d011682016040523d82523d6000602084013e61248b565b606091505b509150915081801561249e575080516020145b80156124ba57506124b681600063ffffffff6130ef16565b6001145b6124c5576000612103565b60001995505050505061189d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561250f57600019915061189d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561189d5760008061254d85610e02565b50925092505061255b613678565b6001600160a01b0316826001600160a01b031614801561258857506005546001600160a01b038281169116145b156126be576005546040516060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916125d2918a916001600160a01b0390911690602401615015565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905060006060612612613690565b6001600160a01b0316836040516126299190614fe5565b600060405180830381855afa9150503d8060008114612664576040519150601f19603f3d011682016040523d82523d6000602084013e612669565b606091505b5091509150600082801561267e575081516020145b61268957600061269a565b61269a82600063ffffffff6130ef16565b905060001981146126b3576126ae816136a8565b6126b7565b6000195b9750505050505b50505092915050565b60006126d1613f0c565b6127248584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b60408051600480825260a0820190925291925060609190816020015b606081526020019060019003908161274057505060408051600480825260a082019092529192506060919060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339019050509050886101600151846000815181106127d657fe5b602002602001018190525087836000815181106127ef57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505088600001518260008151811061282157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050868160008151811061284f57fe5b6020026020010181815250508861014001518460018151811061286e57fe5b602002602001018190525088600001518360018151811061288b57fe5b6001600160a01b0392831660209182029290920101528816156128ae57876128c4565b73377f698c4c287018d09b516f415317aec59193325b826001815181106128d157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084600001518160018151811061290357fe5b602002602001018181525050886101a001518460028151811061292257fe5b6020026020010181905250878360028151811061293b57fe5b6001600160a01b03928316602091820292909201015260408a0151161561296657886040015161297c565b73377f698c4c287018d09b516f415317aec59193325b8260028151811061298957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460600151816002815181106129bb57fe5b602002602001018181525050886101800151846003815181106129da57fe5b60200260200101819052508860000151836003815181106129f757fe5b6001600160a01b03928316602091820292909201015260408a01511615612a22578860400151612a38565b73377f698c4c287018d09b516f415317aec59193325b82600381518110612a4557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160038151811061116757fe5b6040516060906394cfcdd760e01b90611be89085908590602401615276565b6000612aa8828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001480612af257506001600160e01b0319811663012b8bc960e11b145b80612b2657506001600160e01b031981167fa7cb5fb700000000000000000000000000000000000000000000000000000000145b80612b4157506001600160e01b031981166394cfcdd760e01b145b80612b7557506001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000145b610d4d5760405162461bcd60e51b8152600401610885906156a4565b606080606060008551905080604051908082528060200260200182016040528015612bd657816020015b612bc3613f3b565b815260200190600190039081612bbb5790505b50935080604051908082528060200260200182016040528015612c03578160200160208202803883390190505b50925080604051908082528060200260200182016040528015612c30578160200160208202803883390190505b50915060005b818114612cc057612c6d878281518110612c4c57fe5b6020026020010151878381518110612c6057fe5b6020026020010151612ce2565b8751889085908110612c7b57fe5b60200260200101878581518110612c8e57fe5b60200260200101878681518110612ca157fe5b9315156020948502919091019093019290925291905252600101612c36565b50509250925092565b606080612cd68484611e67565b91506108d38484610c5f565b612cea613f3b565b6006546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815260009182916001600160a01b0390911690639d3fa4b990612d389088906004016156ff565b60606040518083038186803b158015612d5057600080fd5b505afa158015612d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d889190810190614a70565b85516006546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f90612dda9089908990600401615712565b60206040518083038186803b158015612df257600080fd5b505afa158015612e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e2a91908101906148b2565b91506000612e3d82886101400151610939565b60a088015160c08901516101808a01516101408b015193945091929091600091612e6c9163ffffffff61394516565b15612e9957612e9284612e8c848d6080015161396a90919063ffffffff16565b85613986565b9050612ef2565b81612ead57612e92848b6080015185613986565b6000612ebe868c6101800151610939565b90506000612ed1868d6080015187613986565b90506000612ee0838688613986565b9050612eec828261311f565b93505050505b612f12612f0c8960400151856139a890919063ffffffff16565b8261311f565b96506004612f258b8c602001518a610ed1565b6004811115612f3057fe5b14612f3c576000612f3e565b865b9650612f4e8a61016001516139c7565b612f5757600096505b60e08a015115801590612f755750612f738a6101a001516139c7565b155b15612f7f57600096505b600388516006811115612f8e57fe5b14612f9857600096505b50505050509250925092565b6000806000612fb5846107f2613ab1565b6000612fce60048651876130459092919063ffffffff16565b8060200190516109199190810190614cbd565b7ffdb6ca8d0000000000000000000000000000000000000000000000000000000090565b6000613012836000613088565b90506001600160e01b0319808216908316146130405760405162461bcd60e51b81526004016108859061566d565b505050565b6060818311156130635761306361305e60008585613ad5565b613af4565b835182111561307c5761307c61305e6001848751613ad5565b50819003910190815290565b600081600401835110156130a9576130a961305e6003855185600401613ad5565b5001602001516001600160e01b03191690565b600081601401835110156130dd576130dd61305e6004855185601401613ad5565b5001601401516001600160a01b031690565b6000610dc18383613afc565b7f18e4b1410000000000000000000000000000000000000000000000000000000090565b600081831061312e5781610dc1565b5090919050565b7f4678472b0000000000000000000000000000000000000000000000000000000090565b7fb6555d6f0000000000000000000000000000000000000000000000000000000090565b7f488219a60000000000000000000000000000000000000000000000000000000090565b7f1b8388f70000000000000000000000000000000000000000000000000000000090565b7fe94a7ed00000000000000000000000000000000000000000000000000000000090565b7f4ad312750000000000000000000000000000000000000000000000000000000090565b6060818311156132265761322661305e60008585613ad5565b835182111561323f5761323f61305e6001848751613ad5565b8282036040519080825280601f01601f19166020018201604052801561326c576020820181803883390190505b509050610dc161327b82613b26565b8461328587613b26565b018351613b2c565b7f11c7b7200000000000000000000000000000000000000000000000000000000090565b6132b9613f0c565b6020810184905260a085015160808601516132d5918691613bd1565b815260a085015160c08601516132ec918691613bd1565b604082015260a085015160e0860151613306918691613bd1565b606082015261331b828463ffffffff613c0516565b6080820152949350505050565b6040516000906060907fb04fbddd0000000000000000000000000000000000000000000000000000000090613367908890889088908890602401615124565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260065491519092506060916001600160a01b0316906133b9908490614fe5565b6000604051808303816000865af19150503d80600081146133f6576040519150601f19603f3d011682016040523d82523d6000602084013e6133fb565b606091505b50915060009050613412828263ffffffff61308816565b905061341c61317d565b6001600160e01b03198281169116141561345957600061343b836109ea565b5091505060ff8116600481111561344e57fe5b94505050505061120d565b613461613135565b6001600160e01b03198281169116141561349457600061348083610961565b509091505060ff8116600481111561344e57fe5b815160208301207ff43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce014156134ce576004935050505061120d565b60405162461bcd60e51b815260040161088590615636565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6000610dc18261354c85613c36565b613cb1565b7fa15c0d060000000000000000000000000000000000000000000000000000000090565b6040516000906060907f70a0823100000000000000000000000000000000000000000000000000000000906135ae908590602401615001565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060856001600160a01b0316836040516135ff9190614fe5565b600060405180830381855afa9150503d806000811461363a576040519150601f19603f3d011682016040523d82523d6000602084013e61363f565b606091505b5091509150818015613652575080516020145b61365d57600061366e565b61366e81600063ffffffff6130ef16565b9695505050505050565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b6000806136b3613690565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156136ed57600080fd5b505af1158015613701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506137259190810190614a54565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561376457600080fd5b505af1158015613778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061379c9190810190614c78565b421161381a57816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156137dd57600080fd5b505af11580156137f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506138159190810190614c78565b61388d565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561385557600080fd5b505af1158015613869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061388d9190810190614c78565b905061120d816b033b2e3c9fd0803ce800000086613986565b7f7e5a23180000000000000000000000000000000000000000000000000000000090565b6000610dc18261354c85613ceb565b7f5bd0428d0000000000000000000000000000000000000000000000000000000090565b7f20d11f610000000000000000000000000000000000000000000000000000000090565b7ff59851840000000000000000000000000000000000000000000000000000000090565b600081518351148015610dc15750508051602091820120825192909101919091201490565b600082820183811015610dc157610dc161305e60008686613da4565b600061120d8361399c868563ffffffff613c0516565b9063ffffffff613dc316565b6000828211156139c1576139c161305e60028585613da4565b50900390565b600060208251816139d457fe5b066004146139e457506000610d4d565b60006139f6838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b14613a1a576001915050610d4d565b606080613a2685611cd6565b80519194509250905060005b818114613aa4576000613a626000858481518110613a4c57fe5b602002602001015161308890919063ffffffff16565b90506001600160e01b0319811663012b8bc960e11b1415613a9b57613a878483613ded565b15613a9b5760009650505050505050610d4d565b50600101613a32565b5060019695505050505050565b7fe53c76c80000000000000000000000000000000000000000000000000000000090565b6060632800659560e01b848484604051602401610d8c939291906155d0565b805160208201fd5b60008160200183511015613b1d57613b1d61305e6005855185602001613ad5565b50016020015190565b60200190565b6020811015613b56576001816020036101000a038019835116818551168082178652505050613040565b82821415613b6357613040565b82821115613b9d5760208103905080820181840181515b82851015613b95578451865260209586019590940193613b7a565b905250613040565b60208103905080820181840183515b81861215613bc85782518252601f199283019290910190613bac565b85525050505050565b6000613bde848484613e50565b15613bf157613bf161305e858585613eb6565b61120d8361399c868563ffffffff613c0516565b600082613c145750600061095b565b82820282848281613c2157fe5b0414610dc157610dc161305e60018686613da4565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a753493909290916020871015613d3757fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b606063e946c1bb60e01b848484604051602401610d8c93929190615561565b600081613dd957613dd961305e60038585613da4565b6000828481613de457fe5b04949350505050565b8151600090600183015b81811015610cda57613e38858281518110613e0e57fe5b6020026020010151868681518110613e2257fe5b602002602001015161394590919063ffffffff16565b15613e485760019250505061095b565b600101613df7565b600082613e6257613e6261305e613ed5565b811580613e6d575083155b15613e7a57506000610dc1565b60008380613e8457fe5b8584099050613e99858463ffffffff613c0516565b613eab826103e863ffffffff613c0516565b101595945050505050565b606063339f3de260e01b848484604051602401610d8c93929190615737565b60408051808201909152600481527fa791837c00000000000000000000000000000000000000000000000000000000602082015290565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040805160608101909152806000815260006020820181905260409091015290565b803561095b81615813565b600082601f830112613f78578081fd5b8135613f8b613f8682615774565b61574d565b818152915060208083019084810181840286018201871015613fac57600080fd5b60005b84811015611898578135613fc281615813565b84529282019290820190600101613faf565b600082601f830112613fe4578081fd5b8151613ff2613f8682615774565b8181529150602080830190840160005b8381101561402f5761401a876020845189010161419b565b83526020928301929190910190600101614002565b5050505092915050565b600082601f830112614049578081fd5b8135614057613f8682615774565b8181529150602080830190840160005b8381101561402f5761407f876020843589010161414d565b83526020928301929190910190600101614067565b600082601f8301126140a4578081fd5b81356140b2613f8682615774565b8181529150602080830190840160005b8381101561402f576140da87602084358901016141e1565b835260209283019291909101906001016140c2565b600082601f8301126140ff578081fd5b813561410d613f8682615774565b81815291506020808301908481018184028601820187101561412e57600080fd5b60005b8481101561189857813584529282019290820190600101614131565b600082601f83011261415d578081fd5b813561416b613f8682615794565b915080825283602082850101111561418257600080fd5b8060208401602084013760009082016020015292915050565b600082601f8301126141ab578081fd5b81516141b9613f8682615794565b91508082528360208285010111156141d057600080fd5b61189d8160208401602086016157b8565b60006101c08083850312156141f4578182fd5b6141fd8161574d565b91505061420a8383613f5d565b81526142198360208401613f5d565b602082015261422b8360408401613f5d565b604082015261423d8360608401613f5d565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561429f57600080fd5b6142ab8683870161414d565b838501526101609250828501359150808211156142c757600080fd5b6142d38683870161414d565b838501526101809250828501359150808211156142ef57600080fd5b6142fb8683870161414d565b838501526101a092508285013591508082111561431757600080fd5b506143248582860161414d565b82840152505092915050565b805160ff8116811461095b57600080fd5b600060208284031215614352578081fd5b8135610dc181615813565b6000806040838503121561436f578081fd5b825161437a81615813565b602084015190925061438b81615813565b809150509250929050565b6000806000606084860312156143aa578081fd5b83516143b581615813565b60208501519093506143c681615813565b604085015190925067ffffffffffffffff8111156143e2578182fd5b6143ee8682870161419b565b9150509250925092565b60008060006060848603121561440c578081fd5b835161441781615813565b602085015190935061442881615813565b80925050604084015190509250925092565b60008060006060848603121561444e578081fd5b835161445981615813565b602085015190935067ffffffffffffffff811115614475578182fd5b6144818682870161419b565b925050604084015190509250925092565b600080600080608085870312156144a7578182fd5b84516144b281615813565b602086015190945067ffffffffffffffff808211156144cf578384fd5b6144db8883890161419b565b945060408701519150808211156144f0578384fd5b6144fc8883890161419b565b93506060870151915080821115614511578283fd5b5061451e8782880161419b565b91505092959194509250565b6000806040838503121561453c578182fd5b823561454781615813565b9150602083013567ffffffffffffffff811115614562578182fd5b61456e85828601614039565b9150509250929050565b6000806000806080858703121561458d578182fd5b843561459881615813565b9350602085013567ffffffffffffffff808211156145b4578384fd5b6145c0888389016140ef565b945060408701359150808211156145d5578384fd5b6145e1888389016140ef565b935060608701359150808211156145f6578283fd5b5061451e8782880161414d565b60008060408385031215614615578182fd5b823561462081615813565b9150602083013567ffffffffffffffff81111561463b578182fd5b61456e8582860161414d565b60008060006060848603121561465b578081fd5b833561466681615813565b9250602084013567ffffffffffffffff811115614681578182fd5b61468d8682870161414d565b925050604084013590509250925092565b600080604083850312156146b0578182fd5b82356146bb81615813565b946020939093013593505050565b6000602082840312156146da578081fd5b813567ffffffffffffffff8111156146f0578182fd5b61120d84828501613f68565b600080600060608486031215614710578081fd5b833567ffffffffffffffff80821115614727578283fd5b61473387838801614094565b94506020860135915080821115614748578283fd5b61475487838801613f68565b93506040860135915080821115614769578283fd5b506143ee868287016140ef565b60008060408385031215614788578182fd5b823567ffffffffffffffff8082111561479f578384fd5b6147ab86838701614094565b935060208501359150808211156147c0578283fd5b5061456e85828601614039565b600080604083850312156147df578182fd5b823567ffffffffffffffff808211156147f6578384fd5b6147ab868387016140ef565b60008060408385031215614814578182fd5b825167ffffffffffffffff8082111561482b578384fd5b81850186601f82011261483c578485fd5b8051925061484c613f8684615774565b80848252602080830192508084018a82838902870101111561486c578889fd5b8894505b8685101561488e578051845260019490940193928101928101614870565b5088015190965093505050808211156148a5578283fd5b5061456e85828601613fd4565b6000602082840312156148c3578081fd5b81518015158114610dc1578182fd5b600080600080608085870312156148e7578182fd5b8451935060208501516148f981615813565b604086015190935067ffffffffffffffff808211156144f0578384fd5b60008060408385031215614928578182fd5b505080516020909101519092909150565b6000806040838503121561494b578182fd5b82519150602083015167ffffffffffffffff811115614968578182fd5b61456e8582860161419b565b600080600060608486031215614988578081fd5b83519250602084015167ffffffffffffffff808211156149a6578283fd5b6149b28783880161419b565b935060408601519150808211156149c7578283fd5b506143ee8682870161419b565b600080604083850312156149e6578182fd5b82519150602083015161438b81615828565b60008060408385031215614a0a578182fd5b82516001600160e01b03198116811461437a578283fd5b600060208284031215614a32578081fd5b813567ffffffffffffffff811115614a48578182fd5b61120d8482850161414d565b600060208284031215614a65578081fd5b8151610dc181615813565b600060608284031215614a81578081fd5b614a8b606061574d565b825160078110614a99578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614acc578081fd5b833567ffffffffffffffff811115614ae2578182fd5b614aee868287016141e1565b9350506020840135614aff81615813565b929592945050506040919091013590565b60008060408385031215614b22578182fd5b823567ffffffffffffffff80821115614b39578384fd5b614b45868387016141e1565b93506020850135915080821115614b5a578283fd5b5061456e8582860161414d565b600080600060608486031215614b7b578081fd5b833567ffffffffffffffff811115614b91578182fd5b614b9d868287016141e1565b935050602084013591506040840135614bb581615813565b809150509250925092565b600080600060608486031215614bd4578081fd5b833567ffffffffffffffff80821115614beb578283fd5b81860160a08189031215614bfd578384fd5b614c0760a061574d565b9250803583526020810135602084015260408101356040840152614c2e8860608301613f5d565b6060840152608081013582811115614c44578485fd5b614c508982840161414d565b608085015250919450505060208401359150614c6f8560408601613f5d565b90509250925092565b600060208284031215614c89578081fd5b5051919050565b60008060408385031215614ca2578182fd5b8251614cad81615828565b6020939093015192949293505050565b600080600060608486031215614cd1578081fd5b8351614cdc81615828565b602085015160408601519194509250614bb581615813565b60008060008060808587031215614d09578182fd5b614d138686614330565b9350602085015192506040850151614d2a81615813565b606086015190925067ffffffffffffffff811115614d46578182fd5b61451e8782880161419b565b600080600060608486031215614d66578081fd5b614d708585614330565b925060208401519150604084015167ffffffffffffffff8111156143e2578182fd5b600080600060608486031215614da6578081fd5b614db08585614330565b925060208401519150604084015190509250925092565b6001600160a01b03169052565b6000815180845260208401935060208301825b82811015614e0e5781516001600160a01b0316865260209586019590910190600101614de7565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b84811015614e63578284038852614e4d848351614ea0565b6020988901989094509190910190600101614e35565b50919695505050505050565b6000815180845260208401935060208301825b82811015614e0e578151865260209586019590910190600101614e82565b60008151808452614eb88160208601602086016157b8565b601f01601f19169290920160200192915050565b8051614ed781615809565b825260208181015190830152604090810151910152565b60006101c0614efe848451614dc7565b6020830151614f106020860182614dc7565b506040830151614f236040860182614dc7565b506060830151614f366060860182614dc7565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152614f8f83870182614ea0565b91505061016091508184015185820383870152614fac8282614ea0565b925050506101808084015185830382870152614fc88382614ea0565b9150506101a09150818401518582038387015261366e8282614ea0565b60008251614ff78184602087016157b8565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0386168252608060208301526150756080830186614e6f565b82810360408401526150878186614e6f565b83810360608501526150998186614ea0565b98975050505050505050565b60006001600160a01b0385168252606060208301526150c76060830185614ea0565b9050826040830152949350505050565b60006001600160a01b0386168252608060208301526150f96080830186614ea0565b82810360408401526150878186614ea0565b6001600160a01b03929092168252602082015260400190565b6000608082526151376080830187614e18565b82810360208401526151498187614dd4565b838103604085015261515b8187614dd4565b91505082810360608401526151708185614e6f565b979650505050505050565b602080825282518282018190526000918401906040840190835b818110156151bd578351600581106151a957fe5b835260209384019390920191600101615195565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561520b576151f8848351614ecc565b60609390930192908401906001016151e5565b5050508381038285015261521f8187614e6f565b84810360408601528551808252908301915082860190845b81811015615255578251151584529284019291840191600101615237565b509198975050505050505050565b600060208252610dc16020830184614e6f565b6000604082526152896040830185614e6f565b828103602084015261529b8185614e18565b95945050505050565b6000604082526152b76040830185614e6f565b828103602084015261529b8185614e6f565b90815260200190565b60008582526001600160a01b0385166020830152608060408301526152fa6080830185614ea0565b82810360608401526151708185614ea0565b918252602082015260400190565b60008382526040602083015261120d6040830184614ea0565b60008482526060602083015261534c6060830185614ea0565b828103604084015261366e8185614ea0565b8281526040810161536e83615809565b8260208301529392505050565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261366e6080830184614ea0565b60006001600160e01b0319871682526001600160a01b038616602083015260a0604083015261542160a0830186614e6f565b82810360608401526154338186614e6f565b838103608085015261117f8186614ea0565b60006001600160e01b0319861682526001600160a01b0385166020830152608060408301526154776080830185614ea0565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b031985168252606060208301526154d66060830185614e6f565b828103604084015261366e8185614e18565b600060208252610dc16020830184614ea0565b60006080825261550e6080830187614ea0565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6000615544856157e8565b8482528360208301526060604083015261529b6060830184614ea0565b6060810161556e856157f5565b938152602081019290925260409091015290565b6060810161558f856157ff565b93815260208101929092526001600160a01b031660409091015290565b604081016155b9846157f5565b9281526020015290565b6060810161556e856157ff565b606081016008851061556e57fe5b60208101600583106155ec57fe5b91905290565b60006155fd86615809565b8582528460208301526001600160a01b03841660408301526080606083015261366e6080830184614ea0565b604081016155b9846157e8565b60208082526013908201527f554e4b4e4f574e5f52455455524e5f4441544100000000000000000000000000604082015260600190565b6020808252600c908201527f4241445f53454c4543544f520000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f57524f4e475f50524f58595f4944000000000000000000000000000000000000604082015260600190565b60a081016156e98286614ecc565b8360608301528215156080830152949350505050565b600060208252610dc16020830184614eee565b6000604082526157256040830185614eee565b828103602084015261529b8185614ea0565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561576c57600080fd5b604052919050565b600067ffffffffffffffff82111561578a578081fd5b5060209081020190565b600067ffffffffffffffff8211156157aa578081fd5b50601f01601f191660200190565b60005b838110156157d35781810151838201526020016157bb565b838111156157e2576000848401525b50505050565b600281106157f257fe5b50565b600481106157f257fe5b600381106157f257fe5b600781106157f257fe5b6001600160a01b03811681146157f257600080fd5b60ff811681146157f257600080fdfea365627a7a72315820b8f5e1baee716487ac576e78a6a19b92db1db8535a5a9d8ed8a3c9e3e2968a386c6578706572696d656e74616cf564736f6c63430005100040" + "object": "0x608060405234801561001057600080fd5b506004361061025c5760003560e01c8063a5cd62ba11610145578063d3637905116100bd578063e4e6e7da1161008c578063ee18599711610071578063ee185997146105b5578063ef3bb097146105bd578063ff84e7cc146105c55761025c565b8063e4e6e7da14610572578063e77286eb146105935761025c565b8063d36379051461050a578063d3d862d11461051d578063d469502814610530578063e25cabf7146105505761025c565b8063c26cfecd11610114578063ca49f47c116100f9578063ca49f47c146104c1578063d001c5dc146104e4578063d186037f146104f75761025c565b8063c26cfecd146104b1578063c82037ef146104b95761025c565b8063a5cd62ba14610449578063a6627e9f14610469578063b43cffe11461047c578063bbb2dcf61461048f5761025c565b80637982653e116101d85780639baf2705116101a75780639eadc8351161018c5780639eadc835146103ff578063a070cac814610423578063a0901e51146104365761025c565b80639baf2705146103e25780639cd01605146103f75761025c565b80637982653e1461037b57806379c9c4261461039b5780637d727512146103ae5780638f4ce479146103c15761025c565b80634dfdac201161022f57806363eb39921161021457806363eb3992146103225780636f83188e14610335578063750bdb30146103585761025c565b80634dfdac20146102e2578063590aa875146103025761025c565b806304a5618a146102615780630d7b7d761461028c5780632322cf76146102ad57806346eb65cb146102cd575b600080fd5b61027461026f36600461406c565b6105cd565b60405161028393929190614abe565b60405180910390f35b61029f61029a366004613b30565b610666565b604051610283929190614ca6565b6102c06102bb366004613b30565b610688565b604051610283919061499b565b6102e06102db36600461406c565b6106b0565b005b6102f56102f0366004613a4b565b610734565b60405161028391906148f3565b610315610310366004613a2f565b6107b7565b6040516102839190614b1e565b610315610330366004613b74565b610866565b61034861034336600461406c565b610919565b6040516102839493929190614bb2565b61036b61036636600461406c565b6109b9565b60405161028394939291906149dc565b61038e610389366004614242565b610a4b565b6040516102839190614b9f565b6102c06103a936600461434a565b610afd565b6102c06103bc366004613b30565b610b7e565b6103d46103cf36600461406c565b611474565b6040516102839291906149b9565b6103ea611507565b604051610283919061465f565b6103ea611516565b61041261040d36600461406c565b611525565b604051610283959493929190614a18565b6102c06104313660046142f1565b6115ca565b6102f5610444366004613bf6565b61164b565b61045c610457366004613cc4565b6116c4565b604051610283919061480c565b610315610477366004613bcb565b61177e565b61031561048a366004613a99565b61182e565b6104a261049d36600461406c565b6118e4565b60405161028393929190614ae9565b6102c0611974565b6103ea61197a565b6104d46104cf36600461406c565b611989565b6040516102839493929190614a7b565b6102f56104f2366004613a4b565b611a1b565b6102c0610505366004613b30565b611a89565b61038e610518366004614242565b612365565b61031561052b366004613d9f565b6123c7565b61054361053e36600461406c565b61241c565b60405161028391906149a4565b61056361055e366004613d48565b6124bf565b60405161028393929190614858565b610585610580366004613a4b565b6125f7565b604051610283929190614976565b6105a66105a136600461429a565b612610565b60405161028393929190614c4a565b6103ea612980565b6103ea61298f565b6103ea61299e565b600080600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a856040518263ffffffff1660e01b81526004016106099190614b1e565b60606040518083038186803b15801561062157600080fd5b505af4158015610635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106599190810190613fc2565b9250925092509193909250565b6000806106738484610b7e565b915061067f8484611a89565b90509250929050565b60008060006106978585610666565b915091506106a582826129ad565b925050505b92915050565b6040517f46eb65cb00000000000000000000000000000000000000000000000000000000815273__$d8b635de2bf4a097b4e18b67d0fb68e779$__906346eb65cb90610700908490600401614b1e565b60006040518083038186803b15801561071857600080fd5b505af415801561072c573d6000803e3d6000fd5b505050505b50565b606060008251905080604051908082528060200260200182016040528015610766578160200160208202803883390190505b50915060005b8181146107af576107908585838151811061078357fe5b6020026020010151611a89565b83828151811061079c57fe5b602090810291909101015260010161076c565b505092915050565b6040517f590aa87500000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063590aa8759061080a90859060040161465f565b60006040518083038186803b15801561082257600080fd5b505af4158015610836573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085e919081019061409f565b90505b919050565b6040517f63eb399200000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__906363eb3992906108bd9087908790879060040161478c565b60006040518083038186803b1580156108d557600080fd5b505af41580156108e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610911919081019061409f565b949350505050565b60608060608073__$fddee3b26a806429350031cf3481976d2e$__636f83188e866040518263ffffffff1660e01b81526004016109569190614b1e565b60006040518083038186803b15801561096e57600080fd5b505af4158015610982573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa919081019061410d565b93509350935093509193509193565b6000806000606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016109f79190614b1e565b60006040518083038186803b158015610a0f57600080fd5b505af4158015610a23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613e46565b600080546040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91639caa023b91610aad916001600160a01b0316908890889088906004016147be565b60206040518083038186803b158015610ac557600080fd5b505af4158015610ad9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061091191908101906140ee565b600061091184610b796040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612a1a565b600080610b91838263ffffffff612a2e16565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610bec576000610bd884601063ffffffff612a6716565b9050610be48186612a9a565b92505061146d565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415610e055760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401610c589190614b1e565b60606040518083038186803b158015610c7057600080fd5b505af4158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ca89190810190613fc2565b6040519194509250606091507f6352211e0000000000000000000000000000000000000000000000000000000090610ce490849060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051610d5f9190614643565b600060405180830381855afa9150503d8060008114610d9a576040519150601f19603f3d011682016040523d82523d6000602084013e610d9f565b606091505b50915091506000828015610db4575081516020145b610dbf576000610dd0565b610dd082600c63ffffffff612a6716565b9050896001600160a01b0316816001600160a01b031614610df2576000610df5565b60015b60ff16975050505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156110a157600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b8152600401610e739190614b1e565b60006040518083038186803b158015610e8b57600080fd5b505af4158015610e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ec79190810190613eb0565b5081519296509094509250905060005b81811461109757828181518110610eea57fe5b602002602001015160001415610eff5761108f565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b90879085908110610f3357fe5b6020026020010151604051602401610f4c9291906147f3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060876001600160a01b031683604051610fc79190614643565b600060405180830381855afa9150503d8060008114611002576040519150601f19603f3d011682016040523d82523d6000602084013e611007565b606091505b5091509150600082801561101c575081516020145b611027576000611038565b61103882600063ffffffff612b9216565b9050600087868151811061104857fe5b6020026020010151828161105857fe5b049050806110745760009b5050505050505050505050506106aa565b8b81108061108057508b155b1561108957809b505b50505050505b600101610ed7565b505050505061146d565b6001600160e01b031981167fc339d10a0000000000000000000000000000000000000000000000000000000014156111d4576040516060907fa85e59e4000000000000000000000000000000000000000000000000000000009061111090869060009081908190602401614b31565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199094169390931790925260045491519092506000916001600160a01b031690611177908490614643565b600060405180830381855afa9150503d80600081146111b2576040519150601f19603f3d011682016040523d82523d6000602084013e6111b7565b606091505b50509050806111c75760006111cb565b6000195b9350505061146d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156112fd5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016112409190614b1e565b60006040518083038186803b15801561125857600080fd5b505af415801561126c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112949190810190613e46565b5092509250506112a2612b9e565b6001600160a01b0316826001600160a01b03161480156112cf57506005546001600160a01b038281169116145b156112f65760006112e76112e1612bb6565b88612a9a565b90506112f281612bce565b9450505b505061146d565b6001600160e01b031981167f94cfcdd700000000000000000000000000000000000000000000000000000000141561146d5760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b81526004016113699190614b1e565b60006040518083038186803b15801561138157600080fd5b505af4158015611395573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113bd9190810190614002565b80519194509250905060005b818114611468578381815181106113dc57fe5b6020026020010151600014156113f157611460565b60006114108985848151811061140357fe5b6020026020010151610b7e565b9050600085838151811061142057fe5b6020026020010151828161143057fe5b049050806114485760009750505050505050506106aa565b87811080611454575087155b1561145d578097505b50505b6001016113c9565b505050505b5092915050565b60008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__638f4ce479846040518263ffffffff1660e01b81526004016114ae9190614b1e565b604080518083038186803b1580156114c557600080fd5b505af41580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114fd9190810190613e0f565b915091505b915091565b6004546001600160a01b031681565b6000546001600160a01b031681565b600080606080606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b81526004016115649190614b1e565b60006040518083038186803b15801561157c57600080fd5b505af4158015611590573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115b89190810190613eb0565b939a9299509097509550909350915050565b6000610911846116466040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612dcc565b6060808251604051908082528060200260200182016040528015611679578160200160208202803883390190505b50905060005b8351811461146d5783818151811061169357fe5b60200260200101516001600160a01b0316318282815181106116b157fe5b602090810291909101015260010161167f565b6000546040517f02cffc4500000000000000000000000000000000000000000000000000000000815260609173__$7a69f714cdde1cb6b62e3c39bc8c94deae$__916302cffc459161172a916001600160a01b039091169088908890889060040161468d565b60006040518083038186803b15801561174257600080fd5b505af4158015611756573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109119190810190613c29565b6040517fa6627e9f00000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063a6627e9f906117d390869086906004016147f3565b60006040518083038186803b1580156117eb57600080fd5b505af41580156117ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611827919081019061409f565b9392505050565b6040517fb43cffe100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063b43cffe190611887908890889088908890600401614746565b60006040518083038186803b15801561189f57600080fd5b505af41580156118b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118db919081019061409f565b95945050505050565b600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6856040518263ffffffff1660e01b81526004016119209190614b1e565b60006040518083038186803b15801561193857600080fd5b505af415801561194c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106599190810190614002565b60065481565b6005546001600160a01b031681565b6000806060600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63ca49f47c866040518263ffffffff1660e01b81526004016119c79190614b1e565b60006040518083038186803b1580156119df57600080fd5b505af41580156119f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613f5a565b606060008251905080604051908082528060200260200182016040528015611a4d578160200160208202803883390190505b50915060005b8181146107af57611a6a8585838151811061140357fe5b838281518110611a7657fe5b6020908102919091010152600101611a53565b600080611a9c838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd7000000000000000000000000000000000000000000000000000000001415611c075760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b8152600401611b0a9190614b1e565b60006040518083038186803b158015611b2257600080fd5b505af4158015611b36573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b5e9190810190614002565b80519194509250905060005b818114611bfc57838181518110611b7d57fe5b602002602001015160001415611b9257611bf4565b6000611ba48985848151811061078357fe5b90506000858381518110611bb457fe5b60200260200101518281611bc457fe5b04905080611bdc5760009750505050505050506106aa565b87811080611be8575087155b15611bf1578097505b50505b600101611b6a565b506106aa9350505050565b6001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415611c68576000611c4c84601063ffffffff612a6716565b600154909150610be490829087906001600160a01b0316612ddb565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415611fb85760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401611cd49190614b1e565b60606040518083038186803b158015611cec57600080fd5b505af4158015611d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d249190810190613fc2565b600254604051929550909350606092507fe985e9c50000000000000000000000000000000000000000000000000000000091611d70918a916001600160a01b0390911690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051611deb9190614643565b600060405180830381855afa9150503d8060008114611e26576040519150601f19603f3d011682016040523d82523d6000602084013e611e2b565b606091505b5091509150811580611e3f57508051602014155b80611e5b5750611e5681600063ffffffff612b9216565b600114155b15611fa9576040516060907f081812fc0000000000000000000000000000000000000000000000000000000090611e9690879060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050856001600160a01b031681604051611f0d9190614643565b600060405180830381855afa9150503d8060008114611f48576040519150601f19603f3d011682016040523d82523d6000602084013e611f4d565b606091505b509093509150828015611f61575081516020145b8015611f9057506002546001600160a01b0316611f8583600c63ffffffff612a6716565b6001600160a01b0316145b611f9b576000611f9e565b60015b60ff16975050611097565b6000199650505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156121df576040517f9eadc83500000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__90639eadc8359061203d908790600401614b1e565b60006040518083038186803b15801561205557600080fd5b505af4158015612069573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120919190810190613eb0565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926120db925089916001600160a01b031690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060836001600160a01b0316836040516121569190614643565b600060405180830381855afa9150503d8060008114612191576040519150601f19603f3d011682016040523d82523d6000602084013e612196565b606091505b50915091508180156121a9575080516020145b80156121c557506121c181600063ffffffff612b9216565b6001145b6121d05760006121d4565b6000195b95505050505061146d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561221b57600019915061146d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561146d5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016122879190614b1e565b60006040518083038186803b15801561229f57600080fd5b505af41580156122b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122db9190810190613e46565b5092509250506122e9612b9e565b6001600160a01b0316826001600160a01b031614801561231657506005546001600160a01b038281169116145b1561235c57600061233b612328612bb6565b60055489906001600160a01b0316612ddb565b905060001981146123545761234f81612bce565b612358565b6000195b9450505b50505092915050565b600080546040517f8dccde0400000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91638dccde0491610aad916001600160a01b0316908890889088906004016147be565b6040517fd3d862d100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d3d862d1906117d39086908690600401614906565b6040517fd469502800000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d46950289061246f908590600401614b1e565b60206040518083038186803b15801561248757600080fd5b505af415801561249b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061085e9190810190613df4565b60608060606000855190508060405190808252806020026020018201604052801561250457816020015b6124f1613467565b8152602001906001900390816124e95790505b50935080604051908082528060200260200182016040528015612531578160200160208202803883390190505b5092508060405190808252806020026020018201604052801561255e578160200160208202803883390190505b50915060005b8181146125ee5761259b87828151811061257a57fe5b602002602001015187838151811061258e57fe5b6020026020010151612610565b87518890859081106125a957fe5b602002602001018785815181106125bc57fe5b602002602001018786815181106125cf57fe5b9315156020948502919091019093019290925291905252600101612564565b50509250925092565b6060806126048484611a1b565b915061067f8484610734565b612618613467565b600080546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815282916001600160a01b031690639d3fa4b990612662908890600401614c6e565b60606040518083038186803b15801561267a57600080fd5b505afa15801561268e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126b291908101906141fa565b85516000546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f906127049089908990600401614c81565b60206040518083038186803b15801561271c57600080fd5b505afa158015612730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127549190810190613dd4565b9150600061276187612ee5565b90506000612782886101800151896101400151612f0190919063ffffffff16565b156127b7576127b0826127a68a60c001518b60800151612f2690919063ffffffff16565b8a60a00151612f42565b9050612824565b60c08801516127d3576127b08289608001518a60a00151612f42565b60006127e4848a6101800151610688565b905060006127fb848b608001518c60a00151612f42565b90506000612812838c60c001518d60a00151612f42565b905061281e82826129ad565b93505050505b61284861284287604001518a60a00151612f6490919063ffffffff16565b826129ad565b9450600460005460208a01516040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__92639caa023b926128b3926001600160a01b03909216918e91908c906004016147be565b60206040518083038186803b1580156128cb57600080fd5b505af41580156128df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061290391908101906140ee565b600481111561290e57fe5b1461291a57600061291c565b845b945061292c886101600151612f83565b61293557600094505b60e0880151158015906129535750612951886101a00151612f83565b155b1561295d57600094505b60038651600681111561296c57fe5b1461297657600094505b5050509250925092565b6001546001600160a01b031681565b6002546001600160a01b031681565b6003546001600160a01b031681565b60008183106129bc5781611827565b5090919050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b600061182782612a2985613138565b6131b3565b60008160040183511015612a5457612a54612a4f60038551856004016131ed565b61325c565b5001602001516001600160e01b03191690565b60008160140183511015612a8857612a88612a4f60048551856014016131ed565b5001601401516001600160a01b031690565b60405160009081906060906001600160a01b038616907f70a082310000000000000000000000000000000000000000000000000000000090612ae090879060240161465f565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612b339190614643565b600060405180830381855afa9150503d8060008114612b6e576040519150601f19603f3d011682016040523d82523d6000602084013e612b73565b606091505b5091509150818015612b86575080516020145b156107af576106a58160005b60006118278383613264565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b600080612bd9612bb6565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c1357600080fd5b505af1158015612c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c4b91908101906140d2565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c8a57600080fd5b505af1158015612c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cc29190810190614402565b4211612d4057816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d0357600080fd5b505af1158015612d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d3b9190810190614402565b612db3565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d7b57600080fd5b505af1158015612d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612db39190810190614402565b9050610911816b033b2e3c9fd0803ce800000086612f42565b600061182782612a298561328e565b60405160009081906060906001600160a01b038716907fdd62ed3e0000000000000000000000000000000000000000000000000000000090612e239088908890602401614673565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612e769190614643565b600060405180830381855afa9150503d8060008114612eb1576040519150601f19603f3d011682016040523d82523d6000602084013e612eb6565b606091505b5091509150818015612ec9575080516020145b15612edc57612ed9816000612b92565b92505b50509392505050565b6000806000612ef384613347565b9150915061091182826129ad565b6000815183511480156118275750508051602091820120825192909101919091201490565b60008282018381101561182757611827612a4f6000868661338a565b600061091183612f58868563ffffffff6133a916565b9063ffffffff6133da16565b600082821115612f7d57612f7d612a4f6002858561338a565b50900390565b60006020825181612f9057fe5b06600414612fa057506000610861565b6000612fb2838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd70000000000000000000000000000000000000000000000000000000014612fef576001915050610861565b6040517fbbb2dcf600000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063bbb2dcf690613042908790600401614b1e565b60006040518083038186803b15801561305a57600080fd5b505af415801561306e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130969190810190614002565b80519093509150600090505b81811461312c5760006130d260008584815181106130bc57fe5b6020026020010151612a2e90919063ffffffff16565b90506001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415613123576131108483613404565b1561312357600095505050505050610861565b506001016130a2565b50600195945050505050565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060632800659560e01b84848460405160240161320c93929190614b91565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b6000816020018351101561328557613285612a4f60058551856020016131ed565b50016020015190565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a7534939092909160208710156132da57fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b600080600483610140015151101561336457506000905080611502565b6133778360000151846101400151610b7e565b6114fd8460000151856101400151611a89565b606063e946c1bb60e01b84848460405160240161320c93929190614b6f565b6000826133b8575060006106aa565b828202828482816133c557fe5b041461182757611827612a4f6001868661338a565b6000816133f0576133f0612a4f6003858561338a565b60008284816133fb57fe5b04949350505050565b8151600090600183015b818110156107af5761344f85828151811061342557fe5b602002602001015186868151811061343957fe5b6020026020010151612f0190919063ffffffff16565b1561345f576001925050506106aa565b60010161340e565b6040805160608101909152806000815260006020820181905260409091015290565b80356106aa81614d59565b80516106aa81614d59565b600082601f8301126134af578081fd5b81356134c26134bd82614cdb565b614cb4565b8181529150602080830190848101818402860182018710156134e357600080fd5b60005b848110156114685781356134f981614d59565b845292820192908201906001016134e6565b600082601f83011261351b578081fd5b81356135296134bd82614cdb565b8181529150602080830190840160005b838110156135665761355187602084358901016136fa565b83526020928301929190910190600101613539565b5050505092915050565b600082601f830112613580578081fd5b815161358e6134bd82614cdb565b8181529150602080830190840160005b83811015613566576135b68760208451890101613748565b8352602092830192919091019060010161359e565b600082601f8301126135db578081fd5b81356135e96134bd82614cdb565b8181529150602080830190840160005b8381101561356657613611876020843589010161379d565b835260209283019291909101906001016135f9565b600082601f830112613636578081fd5b81356136446134bd82614cdb565b81815291506020808301908481018184028601820187101561366557600080fd5b60005b8481101561146857813584529282019290820190600101613668565b600082601f830112613694578081fd5b81516136a26134bd82614cdb565b8181529150602080830190848101818402860182018710156136c357600080fd5b60005b84811015611468578151845292820192908201906001016136c6565b80516001600160e01b0319811681146106aa57600080fd5b600082601f83011261370a578081fd5b81356137186134bd82614cfb565b915080825283602082850101111561372f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112613758578081fd5b81516137666134bd82614cfb565b915080825283602082850101111561377d57600080fd5b61146d816020840160208601614d1f565b8051600581106106aa57600080fd5b60006101c08083850312156137b0578182fd5b6137b981614cb4565b9150506137c68383613489565b81526137d58360208401613489565b60208201526137e78360408401613489565b60408201526137f98360608401613489565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561385b57600080fd5b613867868387016136fa565b8385015261016092508285013591508082111561388357600080fd5b61388f868387016136fa565b838501526101809250828501359150808211156138ab57600080fd5b6138b7868387016136fa565b838501526101a09250828501359150808211156138d357600080fd5b506138e0858286016136fa565b82840152505092915050565b60006101c08083850312156138ff578182fd5b61390881614cb4565b9150506139158383613494565b81526139248360208401613494565b60208201526139368360408401613494565b60408201526139488360608401613494565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156139aa57600080fd5b6139b686838701613748565b838501526101609250828501519150808211156139d257600080fd5b6139de86838701613748565b838501526101809250828501519150808211156139fa57600080fd5b613a0686838701613748565b838501526101a0925082850151915080821115613a2257600080fd5b506138e085828601613748565b600060208284031215613a40578081fd5b813561182781614d59565b60008060408385031215613a5d578081fd5b8235613a6881614d59565b9150602083013567ffffffffffffffff811115613a83578182fd5b613a8f8582860161350b565b9150509250929050565b60008060008060808587031215613aae578182fd5b8435613ab981614d59565b9350602085013567ffffffffffffffff80821115613ad5578384fd5b613ae188838901613626565b94506040870135915080821115613af6578384fd5b613b0288838901613626565b93506060870135915080821115613b17578283fd5b50613b24878288016136fa565b91505092959194509250565b60008060408385031215613b42578182fd5b8235613b4d81614d59565b9150602083013567ffffffffffffffff811115613b68578182fd5b613a8f858286016136fa565b600080600060608486031215613b88578081fd5b8335613b9381614d59565b9250602084013567ffffffffffffffff811115613bae578182fd5b613bba868287016136fa565b925050604084013590509250925092565b60008060408385031215613bdd578182fd5b8235613be881614d59565b946020939093013593505050565b600060208284031215613c07578081fd5b813567ffffffffffffffff811115613c1d578182fd5b6109118482850161349f565b60006020808385031215613c3b578182fd5b825167ffffffffffffffff811115613c51578283fd5b80840185601f820112613c62578384fd5b80519150613c726134bd83614cdb565b8281528381019082850185850284018601891015613c8e578687fd5b8693505b84841015613cb857613ca4898261378e565b835260019390930192918501918501613c92565b50979650505050505050565b600080600060608486031215613cd8578081fd5b833567ffffffffffffffff80821115613cef578283fd5b613cfb878388016135cb565b94506020860135915080821115613d10578283fd5b613d1c8783880161349f565b93506040860135915080821115613d31578283fd5b50613d3e86828701613626565b9150509250925092565b60008060408385031215613d5a578182fd5b823567ffffffffffffffff80821115613d71578384fd5b613d7d868387016135cb565b93506020850135915080821115613d92578283fd5b50613a8f8582860161350b565b60008060408385031215613db1578182fd5b823567ffffffffffffffff80821115613dc8578384fd5b613d7d86838701613626565b600060208284031215613de5578081fd5b81518015158114611827578182fd5b600060208284031215613e05578081fd5b61182783836136e2565b60008060408385031215613e21578182fd5b613e2b84846136e2565b91506020830151613e3b81614d59565b809150509250929050565b60008060008060808587031215613e5b578182fd5b8451613e6681614d6e565b6020860151909450613e7781614d59565b6040860151909350613e8881614d59565b606086015190925067ffffffffffffffff811115613ea4578182fd5b613b2487828801613748565b600080600080600060a08688031215613ec7578283fd5b613ed187876136e2565b94506020860151613ee181614d59565b604087015190945067ffffffffffffffff80821115613efe578485fd5b613f0a89838a01613684565b94506060880151915080821115613f1f578283fd5b613f2b89838a01613684565b93506080880151915080821115613f40578283fd5b50613f4d88828901613748565b9150509295509295909350565b60008060008060808587031215613f6f578182fd5b613f7986866136e2565b93506020850151613f8981614d59565b604086015190935067ffffffffffffffff811115613fa5578283fd5b613fb187828801613748565b606096909601519497939650505050565b600080600060608486031215613fd6578081fd5b613fe085856136e2565b92506020840151613ff081614d59565b80925050604084015190509250925092565b600080600060608486031215614016578081fd5b835161402181614d6e565b602085015190935067ffffffffffffffff8082111561403e578283fd5b61404a87838801613684565b9350604086015191508082111561405f578283fd5b50613d3e86828701613570565b60006020828403121561407d578081fd5b813567ffffffffffffffff811115614093578182fd5b610911848285016136fa565b6000602082840312156140b0578081fd5b815167ffffffffffffffff8111156140c6578182fd5b61091184828501613748565b6000602082840312156140e3578081fd5b815161182781614d59565b6000602082840312156140ff578081fd5b815160058110611827578182fd5b60008060008060808587031215614122578182fd5b845167ffffffffffffffff80821115614139578384fd5b61414588838901613748565b955060209150818701518181111561415b578485fd5b80880189601f82011261416c578586fd5b8051915061417c6134bd83614cdb565b82815284810190828601885b858110156141b15761419f8e8984518801016138ec565b84529287019290870190600101614188565b505060408b01519098509450505050808211156141cc578384fd5b6141d888838901613684565b935060608701519150808211156141ed578283fd5b50613b2487828801613570565b60006060828403121561420b578081fd5b6142156060614cb4565b825160078110614223578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614256578081fd5b833567ffffffffffffffff81111561426c578182fd5b6142788682870161379d565b935050602084013561428981614d59565b929592945050506040919091013590565b600080604083850312156142ac578182fd5b823567ffffffffffffffff808211156142c3578384fd5b6142cf8683870161379d565b935060208501359150808211156142e4578283fd5b50613a8f858286016136fa565b600080600060608486031215614305578081fd5b833567ffffffffffffffff81111561431b578182fd5b6143278682870161379d565b93505060208401359150604084013561433f81614d59565b809150509250925092565b60008060006060848603121561435e578081fd5b833567ffffffffffffffff80821115614375578283fd5b81860160a08189031215614387578384fd5b61439160a0614cb4565b92508035835260208101356020840152604081013560408401526143b88860608301613489565b60608401526080810135828111156143ce578485fd5b6143da898284016136fa565b6080850152509194505050602084013591506143f98560408601613489565b90509250925092565b600060208284031215614413578081fd5b5051919050565b6001600160a01b03169052565b6000815180845260208401935060208301825b828110156144615781516001600160a01b031686526020958601959091019060010161443a565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b848110156144b65782840388526144a08483516144f3565b6020988901989094509190910190600101614488565b50919695505050505050565b6000815180845260208401935060208301825b828110156144615781518652602095860195909101906001016144d5565b6000815180845261450b816020860160208601614d1f565b601f01601f19169290920160200192915050565b80516007811061452b57fe5b825260208181015190830152604090810151910152565b60006101c061455284845161441a565b6020830151614564602086018261441a565b506040830151614577604086018261441a565b50606083015161458a606086018261441a565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e08501526101008084015181860152506101208084015181860152506101408084015182828701526145e3838701826144f3565b9150506101609150818401518582038387015261460082826144f3565b92505050610180808401518583038287015261461c83826144f3565b9150506101a09150818401518582038387015261463982826144f3565b9695505050505050565b60008251614655818460208701614d1f565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6000608082016001600160a01b03871683526080602084015280865180835260a08501915060a060208202860101925060208801845b82811015614712577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608786030184526146fd858351614542565b945060209384019391909101906001016146c3565b5050505082810360408401526147288186614427565b838103606085015261473a81866144c2565b98975050505050505050565b60006001600160a01b03861682526080602083015261476860808301866144c2565b828103604084015261477a81866144c2565b838103606085015261473a81866144f3565b60006001600160a01b0385168252606060208301526147ae60608301856144f3565b9050826040830152949350505050565b60006001600160a01b038087168352608060208401526147e16080840187614542565b94166040830152506060015292915050565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000918401906040840190835b8181101561484d57835161483981614d4f565b835260209384019390920191600101614826565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561489b5761488884835161451f565b6060939093019290840190600101614875565b505050838103828501526148af81876144c2565b84810360408601528551808252908301915082860190845b818110156148e55782511515845292840192918401916001016148c7565b509198975050505050505050565b60006020825261182760208301846144c2565b60006040825261491960408301856144c2565b602083820381850152818551808452828401915082838202850101838801865b8381101561496757601f198784030185526149558383516144f3565b94860194925090850190600101614939565b50909998505050505050505050565b60006040825261498960408301856144c2565b82810360208401526118db81856144c2565b90815260200190565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261463960808301846144f3565b60006001600160e01b0319871682526001600160a01b038616602083015260a06040830152614a4a60a08301866144c2565b8281036060840152614a5c81866144c2565b8381036080850152614a6e81866144f3565b9998505050505050505050565b60006001600160e01b0319861682526001600160a01b038516602083015260806040830152614aad60808301856144f3565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b03198516825260606020830152614b0c60608301856144c2565b8281036040840152614639818561446b565b60006020825261182760208301846144f3565b600060808252614b4460808301876144f3565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6060810160048510614b7d57fe5b938152602081019290925260409091015290565b6060810160088510614b7d57fe5b60208101614bac83614d4f565b91905290565b600060808252614bc560808301876144f3565b602083820381850152818751808452828401915082838202850101838a01865b83811015614c1357601f19878403018552614c01838351614542565b94860194925090850190600101614be5565b50508681036040880152614c27818a6144c2565b9450505050508281036060840152614c3f818561446b565b979650505050505050565b60a08101614c58828661451f565b8360608301528215156080830152949350505050565b6000602082526118276020830184614542565b600060408252614c946040830185614542565b82810360208401526118db81856144f3565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715614cd357600080fd5b604052919050565b600067ffffffffffffffff821115614cf1578081fd5b5060209081020190565b600067ffffffffffffffff821115614d11578081fd5b50601f01601f191660200190565b60005b83811015614d3a578181015183820152602001614d22565b83811115614d49576000848401525b50505050565b6005811061073157fe5b6001600160a01b038116811461073157600080fd5b6001600160e01b03198116811461073157600080fdfea365627a7a7231582034aeeb2766e909a7bf6404cf5556e26fa49952bdd5ea533d25447be58f55ed9a6c6578706572696d656e74616cf564736f6c63430005100040" } } }, diff --git a/packages/contract-artifacts/artifacts/LibTransactionDecoder.json b/packages/contract-artifacts/artifacts/LibTransactionDecoder.json deleted file mode 100644 index 7aaf6848c9..0000000000 --- a/packages/contract-artifacts/artifacts/LibTransactionDecoder.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "schemaVersion": "2.0.0", - "contractName": "LibTransactionDecoder", - "compilerOutput": { - "abi": [ - { - "constant": true, - "inputs": [{ "internalType": "bytes", "name": "transactionData", "type": "bytes" }], - "name": "decodeZeroExTransactionData", - "outputs": [ - { "internalType": "string", "name": "functionName", "type": "string" }, - { - "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": "uint256[]", "name": "takerAssetFillAmounts", "type": "uint256[]" }, - { "internalType": "bytes[]", "name": "signatures", "type": "bytes[]" } - ], - "payable": false, - "stateMutability": "pure", - "type": "function" - } - ], - "devdoc": { - "methods": { - "decodeZeroExTransactionData(bytes)": { - "details": "Decodes the call data for an Exchange contract method call.", - "params": { "transactionData": "ABI-encoded calldata for an Exchange contract method call." }, - "return": "The name of the function called, and the parameters it was given. For single-order fills and cancels, the arrays will have just one element." - } - } - }, - "evm": { - "bytecode": { - "object": "0x608060405234801561001057600080fd5b5061198b806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80636f83188e14610030575b600080fd5b61004361003e3660046113f4565b61005c565b604051610053949392919061176e565b60405180910390f35b60608080806000610073868263ffffffff610ba616565b90506001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156100e4576040518060400160405280601181526020017f626174636843616e63656c4f7264657273000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9694a402000000000000000000000000000000000000000000000000000000001415610153576040518060400160405280600f81526020017f626174636846696c6c4f72646572730000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f8ea8dfe40000000000000000000000000000000000000000000000000000000014156101c2576040518060400160405280601681526020017f626174636846696c6c4f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167fbeee2e14000000000000000000000000000000000000000000000000000000001415610231576040518060400160405280601581526020017f626174636846696c6c4f724b696c6c4f72646572730000000000000000000000815250945061067c565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156102a0576040518060400160405280600b81526020017f63616e63656c4f72646572000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000141561030f576040518060400160405280600981526020017f66696c6c4f726465720000000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000141561037e576040518060400160405280600f81526020017f66696c6c4f724b696c6c4f726465720000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f78d29ac10000000000000000000000000000000000000000000000000000000014156103ed576040518060400160405280601681526020017f6d61726b65744275794f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000141561045c576040518060400160405280601781526020017f6d61726b657453656c6c4f72646572734e6f5468726f77000000000000000000815250945061067c565b6001600160e01b031981167f8bc8efb30000000000000000000000000000000000000000000000000000000014156104cb576040518060400160405280601981526020017f6d61726b65744275794f726465727346696c6c4f724b696c6c00000000000000815250945061067c565b6001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000141561053a576040518060400160405280601a81526020017f6d61726b657453656c6c4f726465727346696c6c4f724b696c6c000000000000815250945061067c565b6001600160e01b031981167f88ec79fb0000000000000000000000000000000000000000000000000000000014156105a9576040518060400160405280600b81526020017f6d617463684f7264657273000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f4f9559b100000000000000000000000000000000000000000000000000000000148061060a57506001600160e01b031981167f2280c91000000000000000000000000000000000000000000000000000000000145b1561064a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106419061186d565b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064190611836565b6001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156107215785516106c490879060049063ffffffff610be916565b8060200190516106d79190810190611289565b604080516000808252602082019092529195505b5060408051600080825260208201909252919450610719565b60608152602001906001900390816107045790505b509150610b9e565b6001600160e01b031981167fbeee2e1400000000000000000000000000000000000000000000000000000000148061078257506001600160e01b031981167f9694a40200000000000000000000000000000000000000000000000000000000145b806107b657506001600160e01b031981167f8ea8dfe400000000000000000000000000000000000000000000000000000000145b156107d0576107c486610c70565b91955093509150610b9e565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156108b85760408051600180825281830190925290816020015b61081f610f3d565b815260200190600190039081610817575050865190945061084a90879060049063ffffffff610be916565b80602001905161085d919081019061146b565b8460008151811061086a57fe5b602002602001018190525060006040519080825280602002602001820160405280156106eb578160200160208202803883390190505060408051600080825260208201909252919450610719565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000148061091957506001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000145b15610927576107c486610cac565b6001600160e01b031981167f78d29ac100000000000000000000000000000000000000000000000000000000148061098857506001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000145b806109bc57506001600160e01b031981167f8bc8efb300000000000000000000000000000000000000000000000000000000145b806109f057506001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000145b156109fe576107c486610da6565b6001600160e01b031981167f88ec79fb000000000000000000000000000000000000000000000000000000001415610b9e57610a38610f3d565b610a40610f3d565b606080610a5a60048b518c610be99092919063ffffffff16565b806020019051610a6d919081019061149e565b604080516002808252606082019092529498509296509094509250816020015b610a95610f3d565b815260200190600190039081610a8d5790505097508388600081518110610ab857fe5b60200260200101819052508288600181518110610ad157fe5b602090810291909101015260408051600280825260608201909252908160200160208202803883390190505096508360a0015187600081518110610b1157fe5b6020026020010181815250508260a0015187600181518110610b2f57fe5b60209081029190910101526040805160028082526060820190925290816020015b6060815260200190600190039081610b505790505095508186600081518110610b7557fe5b60200260200101819052508086600181518110610b8e57fe5b6020026020010181905250505050505b509193509193565b60008160040183511015610bcc57610bcc610bc76003855185600401610e1a565b610e89565b5060208183018101519101906001600160e01b0319165b92915050565b606081831115610c0257610c02610bc760008585610e1a565b8351821115610c1b57610c1b610bc76001848751610e1a565b8282036040519080825280601f01601f191660200182016040528015610c48576020820181803883390190505b509050610c69610c5782610e91565b84610c6187610e91565b018351610e97565b9392505050565b6060806060610c8c6004855186610be99092919063ffffffff16565b806020019051610c9f91908101906112c4565b9196909550909350915050565b60408051600180825281830190925260609182918291816020015b610ccf610f3d565b815260200190600190039081610cc75750506040805160018082528183019092529194506020808301908038833901905050604080516001808252818301909252919350816020015b6060815260200190600190039081610d185750508451909150610d4590859060049063ffffffff610be916565b806020019051610d589190810190611546565b85600081518110610d6557fe5b6020026020010185600081518110610d7957fe5b6020026020010185600081518110610d8d57fe5b6020908102919091010192909252919052529193909250565b604080516001808252818301909252606091829182916020808301908038833950508551919350610de29186915060049063ffffffff610be916565b806020019051610df591908101906113a1565b84518590600090610e0257fe5b60209081029190910101919091529095929450925050565b6060632800659560e01b848484604051602401610e399392919061174c565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b60200190565b6020811015610ec1576001816020036101000a038019835116818551168082178652505050610f38565b82821415610ece57610f38565b82821115610f085760208103905080820181840181515b82851015610f00578451865260209586019590940193610ee5565b905250610f38565b60208103905080820181840183515b81861215610f335782518252601f199283019290910190610f17565b855250505b505050565b604051806101c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b805173ffffffffffffffffffffffffffffffffffffffff81168114610be357600080fd5b600082601f830112611038578081fd5b815161104b611046826118cb565b6118a4565b8181529150602080830190840160005b838110156110885761107387602084518901016110ed565b8352602092830192919091019060010161105b565b5050505092915050565b600082601f8301126110a2578081fd5b81516110b0611046826118cb565b8181529150602080830190840160005b83811015611088576110d8876020845189010161113a565b835260209283019291909101906001016110c0565b600082601f8301126110fd578081fd5b815161110b611046826118eb565b915080825283602082850101111561112257600080fd5b611133816020840160208601611918565b5092915050565b60006101c080838503121561114d578182fd5b611156816118a4565b9150506111638383611004565b81526111728360208401611004565b60208201526111848360408401611004565b60408201526111968360608401611004565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156111f857600080fd5b611204868387016110ed565b8385015261016092508285015191508082111561122057600080fd5b61122c868387016110ed565b8385015261018092508285015191508082111561124857600080fd5b611254868387016110ed565b838501526101a092508285015191508082111561127057600080fd5b5061127d858286016110ed565b82840152505092915050565b60006020828403121561129a578081fd5b815167ffffffffffffffff8111156112b0578182fd5b6112bc84828501611092565b949350505050565b6000806000606084860312156112d8578182fd5b835167ffffffffffffffff808211156112ef578384fd5b6112fb87838801611092565b9450602091508186015181811115611311578485fd5b80870188601f820112611322578586fd5b80519150611332611046836118cb565b82815284810190828601868502840187018c101561134e578889fd5b8893505b84841015611370578051835260019390930192918601918601611352565b5060408a015190975094505050508082111561138a578283fd5b5061139786828701611028565b9150509250925092565b6000806000606084860312156113b5578283fd5b835167ffffffffffffffff808211156113cc578485fd5b6113d887838801611092565b945060208601519350604086015191508082111561138a578283fd5b600060208284031215611405578081fd5b813567ffffffffffffffff81111561141b578182fd5b80830184601f82011261142c578283fd5b8035915061143c611046836118eb565b828152856020848401011115611450578384fd5b82602083016020830137918201602001929092529392505050565b60006020828403121561147c578081fd5b815167ffffffffffffffff811115611492578182fd5b6112bc8482850161113a565b600080600080608085870312156114b3578081fd5b845167ffffffffffffffff808211156114ca578283fd5b6114d68883890161113a565b955060208701519150808211156114eb578283fd5b6114f78883890161113a565b9450604087015191508082111561150c578283fd5b611518888389016110ed565b9350606087015191508082111561152d578283fd5b5061153a878288016110ed565b91505092959194509250565b60008060006060848603121561155a578283fd5b835167ffffffffffffffff80821115611571578485fd5b61157d8783880161113a565b9450602086015193506040860151915080821115611599578283fd5b50611397868287016110ed565b60006101c06115b68484516116af565b60208301516115c860208601826116af565b5060408301516115db60408601826116af565b5060608301516115ee60608601826116af565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151828287015261164783870182611720565b915050610160915081840151858203838701526116648282611720565b9250505061018080840151858303828701526116808382611720565b9150506101a09150818401518582038387015261169d8282611720565b9695505050505050565b815260200190565b73ffffffffffffffffffffffffffffffffffffffff169052565b600081518084526020840180819550602083028101915060208501845b848110156117145782840388526116fe848351611720565b60209889019890945091909101906001016116e6565b50919695505050505050565b60008151808452611738816020860160208601611918565b601f01601f19169290920160200192915050565b606081016008851061175a57fe5b938152602081019290925260409091015290565b6000608082526117816080830187611720565b602083820381850152818751611797818561190f565b91508193508281028201838a01865b838110156117d05786830385526117be8383516115a6565b948601949250908501906001016117a6565b50508681036040880152809450885192506117eb838261190f565b94505050818701845b82811015611815576118078583516116a7565b9450908301906001016117f4565b50505050828103606084015261182b81856116c9565b979650505050505050565b60208082526019908201527f554e4b4e4f574e5f46554e4354494f4e5f53454c4543544f5200000000000000604082015260600190565b6020808252600d908201527f554e494d504c454d454e54454400000000000000000000000000000000000000604082015260600190565b60405181810167ffffffffffffffff811182821017156118c357600080fd5b604052919050565b600067ffffffffffffffff8211156118e1578081fd5b5060209081020190565b600067ffffffffffffffff821115611901578081fd5b50601f01601f191660200190565b90815260200190565b60005b8381101561193357818101518382015260200161191b565b83811115611942576000848401525b5050505056fea365627a7a72315820884abdfe69fd82b726a34318b3e10d0da6e8c516e328d10258429ee105f0ad396c6578706572696d656e74616cf564736f6c63430005100040" - }, - "deployedBytecode": { - "object": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80636f83188e14610030575b600080fd5b61004361003e3660046113f4565b61005c565b604051610053949392919061176e565b60405180910390f35b60608080806000610073868263ffffffff610ba616565b90506001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156100e4576040518060400160405280601181526020017f626174636843616e63656c4f7264657273000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9694a402000000000000000000000000000000000000000000000000000000001415610153576040518060400160405280600f81526020017f626174636846696c6c4f72646572730000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f8ea8dfe40000000000000000000000000000000000000000000000000000000014156101c2576040518060400160405280601681526020017f626174636846696c6c4f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167fbeee2e14000000000000000000000000000000000000000000000000000000001415610231576040518060400160405280601581526020017f626174636846696c6c4f724b696c6c4f72646572730000000000000000000000815250945061067c565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156102a0576040518060400160405280600b81526020017f63616e63656c4f72646572000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000141561030f576040518060400160405280600981526020017f66696c6c4f726465720000000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000141561037e576040518060400160405280600f81526020017f66696c6c4f724b696c6c4f726465720000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f78d29ac10000000000000000000000000000000000000000000000000000000014156103ed576040518060400160405280601681526020017f6d61726b65744275794f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000141561045c576040518060400160405280601781526020017f6d61726b657453656c6c4f72646572734e6f5468726f77000000000000000000815250945061067c565b6001600160e01b031981167f8bc8efb30000000000000000000000000000000000000000000000000000000014156104cb576040518060400160405280601981526020017f6d61726b65744275794f726465727346696c6c4f724b696c6c00000000000000815250945061067c565b6001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000141561053a576040518060400160405280601a81526020017f6d61726b657453656c6c4f726465727346696c6c4f724b696c6c000000000000815250945061067c565b6001600160e01b031981167f88ec79fb0000000000000000000000000000000000000000000000000000000014156105a9576040518060400160405280600b81526020017f6d617463684f7264657273000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f4f9559b100000000000000000000000000000000000000000000000000000000148061060a57506001600160e01b031981167f2280c91000000000000000000000000000000000000000000000000000000000145b1561064a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106419061186d565b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064190611836565b6001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156107215785516106c490879060049063ffffffff610be916565b8060200190516106d79190810190611289565b604080516000808252602082019092529195505b5060408051600080825260208201909252919450610719565b60608152602001906001900390816107045790505b509150610b9e565b6001600160e01b031981167fbeee2e1400000000000000000000000000000000000000000000000000000000148061078257506001600160e01b031981167f9694a40200000000000000000000000000000000000000000000000000000000145b806107b657506001600160e01b031981167f8ea8dfe400000000000000000000000000000000000000000000000000000000145b156107d0576107c486610c70565b91955093509150610b9e565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156108b85760408051600180825281830190925290816020015b61081f610f3d565b815260200190600190039081610817575050865190945061084a90879060049063ffffffff610be916565b80602001905161085d919081019061146b565b8460008151811061086a57fe5b602002602001018190525060006040519080825280602002602001820160405280156106eb578160200160208202803883390190505060408051600080825260208201909252919450610719565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000148061091957506001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000145b15610927576107c486610cac565b6001600160e01b031981167f78d29ac100000000000000000000000000000000000000000000000000000000148061098857506001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000145b806109bc57506001600160e01b031981167f8bc8efb300000000000000000000000000000000000000000000000000000000145b806109f057506001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000145b156109fe576107c486610da6565b6001600160e01b031981167f88ec79fb000000000000000000000000000000000000000000000000000000001415610b9e57610a38610f3d565b610a40610f3d565b606080610a5a60048b518c610be99092919063ffffffff16565b806020019051610a6d919081019061149e565b604080516002808252606082019092529498509296509094509250816020015b610a95610f3d565b815260200190600190039081610a8d5790505097508388600081518110610ab857fe5b60200260200101819052508288600181518110610ad157fe5b602090810291909101015260408051600280825260608201909252908160200160208202803883390190505096508360a0015187600081518110610b1157fe5b6020026020010181815250508260a0015187600181518110610b2f57fe5b60209081029190910101526040805160028082526060820190925290816020015b6060815260200190600190039081610b505790505095508186600081518110610b7557fe5b60200260200101819052508086600181518110610b8e57fe5b6020026020010181905250505050505b509193509193565b60008160040183511015610bcc57610bcc610bc76003855185600401610e1a565b610e89565b5060208183018101519101906001600160e01b0319165b92915050565b606081831115610c0257610c02610bc760008585610e1a565b8351821115610c1b57610c1b610bc76001848751610e1a565b8282036040519080825280601f01601f191660200182016040528015610c48576020820181803883390190505b509050610c69610c5782610e91565b84610c6187610e91565b018351610e97565b9392505050565b6060806060610c8c6004855186610be99092919063ffffffff16565b806020019051610c9f91908101906112c4565b9196909550909350915050565b60408051600180825281830190925260609182918291816020015b610ccf610f3d565b815260200190600190039081610cc75750506040805160018082528183019092529194506020808301908038833901905050604080516001808252818301909252919350816020015b6060815260200190600190039081610d185750508451909150610d4590859060049063ffffffff610be916565b806020019051610d589190810190611546565b85600081518110610d6557fe5b6020026020010185600081518110610d7957fe5b6020026020010185600081518110610d8d57fe5b6020908102919091010192909252919052529193909250565b604080516001808252818301909252606091829182916020808301908038833950508551919350610de29186915060049063ffffffff610be916565b806020019051610df591908101906113a1565b84518590600090610e0257fe5b60209081029190910101919091529095929450925050565b6060632800659560e01b848484604051602401610e399392919061174c565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b60200190565b6020811015610ec1576001816020036101000a038019835116818551168082178652505050610f38565b82821415610ece57610f38565b82821115610f085760208103905080820181840181515b82851015610f00578451865260209586019590940193610ee5565b905250610f38565b60208103905080820181840183515b81861215610f335782518252601f199283019290910190610f17565b855250505b505050565b604051806101c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b805173ffffffffffffffffffffffffffffffffffffffff81168114610be357600080fd5b600082601f830112611038578081fd5b815161104b611046826118cb565b6118a4565b8181529150602080830190840160005b838110156110885761107387602084518901016110ed565b8352602092830192919091019060010161105b565b5050505092915050565b600082601f8301126110a2578081fd5b81516110b0611046826118cb565b8181529150602080830190840160005b83811015611088576110d8876020845189010161113a565b835260209283019291909101906001016110c0565b600082601f8301126110fd578081fd5b815161110b611046826118eb565b915080825283602082850101111561112257600080fd5b611133816020840160208601611918565b5092915050565b60006101c080838503121561114d578182fd5b611156816118a4565b9150506111638383611004565b81526111728360208401611004565b60208201526111848360408401611004565b60408201526111968360608401611004565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156111f857600080fd5b611204868387016110ed565b8385015261016092508285015191508082111561122057600080fd5b61122c868387016110ed565b8385015261018092508285015191508082111561124857600080fd5b611254868387016110ed565b838501526101a092508285015191508082111561127057600080fd5b5061127d858286016110ed565b82840152505092915050565b60006020828403121561129a578081fd5b815167ffffffffffffffff8111156112b0578182fd5b6112bc84828501611092565b949350505050565b6000806000606084860312156112d8578182fd5b835167ffffffffffffffff808211156112ef578384fd5b6112fb87838801611092565b9450602091508186015181811115611311578485fd5b80870188601f820112611322578586fd5b80519150611332611046836118cb565b82815284810190828601868502840187018c101561134e578889fd5b8893505b84841015611370578051835260019390930192918601918601611352565b5060408a015190975094505050508082111561138a578283fd5b5061139786828701611028565b9150509250925092565b6000806000606084860312156113b5578283fd5b835167ffffffffffffffff808211156113cc578485fd5b6113d887838801611092565b945060208601519350604086015191508082111561138a578283fd5b600060208284031215611405578081fd5b813567ffffffffffffffff81111561141b578182fd5b80830184601f82011261142c578283fd5b8035915061143c611046836118eb565b828152856020848401011115611450578384fd5b82602083016020830137918201602001929092529392505050565b60006020828403121561147c578081fd5b815167ffffffffffffffff811115611492578182fd5b6112bc8482850161113a565b600080600080608085870312156114b3578081fd5b845167ffffffffffffffff808211156114ca578283fd5b6114d68883890161113a565b955060208701519150808211156114eb578283fd5b6114f78883890161113a565b9450604087015191508082111561150c578283fd5b611518888389016110ed565b9350606087015191508082111561152d578283fd5b5061153a878288016110ed565b91505092959194509250565b60008060006060848603121561155a578283fd5b835167ffffffffffffffff80821115611571578485fd5b61157d8783880161113a565b9450602086015193506040860151915080821115611599578283fd5b50611397868287016110ed565b60006101c06115b68484516116af565b60208301516115c860208601826116af565b5060408301516115db60408601826116af565b5060608301516115ee60608601826116af565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151828287015261164783870182611720565b915050610160915081840151858203838701526116648282611720565b9250505061018080840151858303828701526116808382611720565b9150506101a09150818401518582038387015261169d8282611720565b9695505050505050565b815260200190565b73ffffffffffffffffffffffffffffffffffffffff169052565b600081518084526020840180819550602083028101915060208501845b848110156117145782840388526116fe848351611720565b60209889019890945091909101906001016116e6565b50919695505050505050565b60008151808452611738816020860160208601611918565b601f01601f19169290920160200192915050565b606081016008851061175a57fe5b938152602081019290925260409091015290565b6000608082526117816080830187611720565b602083820381850152818751611797818561190f565b91508193508281028201838a01865b838110156117d05786830385526117be8383516115a6565b948601949250908501906001016117a6565b50508681036040880152809450885192506117eb838261190f565b94505050818701845b82811015611815576118078583516116a7565b9450908301906001016117f4565b50505050828103606084015261182b81856116c9565b979650505050505050565b60208082526019908201527f554e4b4e4f574e5f46554e4354494f4e5f53454c4543544f5200000000000000604082015260600190565b6020808252600d908201527f554e494d504c454d454e54454400000000000000000000000000000000000000604082015260600190565b60405181810167ffffffffffffffff811182821017156118c357600080fd5b604052919050565b600067ffffffffffffffff8211156118e1578081fd5b5060209081020190565b600067ffffffffffffffff821115611901578081fd5b50601f01601f191660200190565b90815260200190565b60005b8381101561193357818101518382015260200161191b565b83811115611942576000848401525b5050505056fea365627a7a72315820884abdfe69fd82b726a34318b3e10d0da6e8c516e328d10258429ee105f0ad396c6578706572696d656e74616cf564736f6c63430005100040" - } - } - }, - "compiler": { - "name": "solc", - "version": "soljson-v0.5.16+commit.9c3226ce.js", - "settings": { - "optimizer": { - "enabled": true, - "runs": 5000, - "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 f4678b2976..c9f07ebfb6 100644 --- a/packages/contract-artifacts/src/index.ts +++ b/packages/contract-artifacts/src/index.ts @@ -15,7 +15,6 @@ import * as Forwarder from '../artifacts/Forwarder.json'; import * as IAssetProxy from '../artifacts/IAssetProxy.json'; import * as IValidator from '../artifacts/IValidator.json'; import * as IWallet from '../artifacts/IWallet.json'; -import * as LibTransactionDecoder from '../artifacts/LibTransactionDecoder.json'; import * as MultiAssetProxy from '../artifacts/MultiAssetProxy.json'; import * as Staking from '../artifacts/Staking.json'; import * as StakingProxy from '../artifacts/StakingProxy.json'; @@ -43,7 +42,6 @@ export { IAssetProxy, IValidator, IWallet, - LibTransactionDecoder, MultiAssetProxy, StaticCallProxy, WETH9, diff --git a/packages/contract-artifacts/tsconfig.json b/packages/contract-artifacts/tsconfig.json index 681825c0cf..36866ab760 100644 --- a/packages/contract-artifacts/tsconfig.json +++ b/packages/contract-artifacts/tsconfig.json @@ -19,7 +19,6 @@ "./artifacts/ERC721Token.json", "./artifacts/Exchange.json", "./artifacts/Forwarder.json", - "./artifacts/LibTransactionDecoder.json", "./artifacts/IAssetProxy.json", "./artifacts/IValidator.json", "./artifacts/IWallet.json", diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index fc1218e2a4..fba01cde16 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -3,8 +3,12 @@ "version": "13.4.1", "changes": [ { - "note": "export `evmbytecodeoutputlinkreferences` type.", + "note": "Export `EvmBytecodeOutputLinkReferences` type.", "pr": 2462 + }, + { + "note": "Remove `LibTransactionDecoder`", + "pr": 2464 } ] }, diff --git a/packages/contract-wrappers/src/contract_wrappers.ts b/packages/contract-wrappers/src/contract_wrappers.ts index 3057564899..a7e14f3304 100644 --- a/packages/contract-wrappers/src/contract_wrappers.ts +++ b/packages/contract-wrappers/src/contract_wrappers.ts @@ -11,7 +11,6 @@ import { ERC20TokenContract } from './generated-wrappers/erc20_token'; import { ERC721TokenContract } from './generated-wrappers/erc721_token'; import { ExchangeContract } from './generated-wrappers/exchange'; import { ForwarderContract } from './generated-wrappers/forwarder'; -import { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder'; import { StakingContract } from './generated-wrappers/staking'; import { WETH9Contract } from './generated-wrappers/weth9'; import { ContractWrappersConfig } from './types'; @@ -50,10 +49,6 @@ export class ContractWrappers { * An instance of the StakingContract class containing methods for interacting with the Staking contracts. */ public staking: StakingContract; - /** - * An instance of the LibTransactionDecoder class containing methods for interacting with the LibTransactionDecoder smart contract. - */ - public libTransactionDecoder: LibTransactionDecoderContract; private readonly _web3Wrapper: Web3Wrapper; /** @@ -78,7 +73,6 @@ export class ContractWrappers { ForwarderContract, StakingContract, WETH9Contract, - LibTransactionDecoderContract, ]; contractsArray.forEach(contract => { this._web3Wrapper.abiDecoder.addABI(contract.ABI(), contract.contractName); @@ -93,10 +87,6 @@ export class ContractWrappers { this.staking = new StakingContract(contractAddresses.stakingProxy, this.getProvider()); this.devUtils = new DevUtilsContract(contractAddresses.devUtils, this.getProvider()); this.coordinator = new CoordinatorContract(contractAddresses.coordinator, this.getProvider()); - this.libTransactionDecoder = new LibTransactionDecoderContract( - contractAddresses.libTransactionDecoder, - this.getProvider(), - ); this.contractAddresses = contractAddresses; } /** diff --git a/packages/contract-wrappers/src/generated-wrappers/coordinator.ts b/packages/contract-wrappers/src/generated-wrappers/coordinator.ts index fdc8ae55df..dc93779d2e 100644 --- a/packages/contract-wrappers/src/generated-wrappers/coordinator.ts +++ b/packages/contract-wrappers/src/generated-wrappers/coordinator.ts @@ -9,6 +9,7 @@ import { BaseContract, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -25,7 +26,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -33,6 +34,7 @@ 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 CoordinatorContract extends BaseContract { @@ -78,6 +80,53 @@ export class CoordinatorContract extends BaseContract { chainId, ); } + + public static async deployWithLibrariesFrom0xArtifactAsync( + artifact: ContractArtifact, + libraryArtifacts: { [libraryName: string]: ContractArtifact }, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + exchange: string, + chainId: BigNumber, + ): 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 CoordinatorContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return CoordinatorContract.deployAsync( + bytecode, + abi, + provider, + txDefaults, + logDecodeDependenciesAbiOnly, + exchange, + chainId, + ); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -456,12 +505,64 @@ export class CoordinatorContract extends BaseContract { 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 CoordinatorContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = CoordinatorContract.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 CoordinatorContract; @@ -469,6 +570,7 @@ export class CoordinatorContract extends BaseContract { 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 CoordinatorContract; @@ -476,6 +578,7 @@ export class CoordinatorContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as CoordinatorContract; @@ -688,7 +791,15 @@ export class CoordinatorContract extends BaseContract { }> > { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue< @@ -840,7 +951,15 @@ export class CoordinatorContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); diff --git a/packages/contract-wrappers/src/generated-wrappers/dev_utils.ts b/packages/contract-wrappers/src/generated-wrappers/dev_utils.ts index bb24dc4a88..9ec98e9f09 100644 --- a/packages/contract-wrappers/src/generated-wrappers/dev_utils.ts +++ b/packages/contract-wrappers/src/generated-wrappers/dev_utils.ts @@ -9,6 +9,7 @@ import { BaseContract, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -25,7 +26,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -33,6 +34,7 @@ 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 DevUtilsContract extends BaseContract { @@ -40,7 +42,7 @@ export class DevUtilsContract extends BaseContract { * @ignore */ public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106102f45760003560e01c80639a7e752611610191578063ca49f47c116100e3578063d3d862d111610097578063e4e6e7da11610071578063e4e6e7da1461077e578063e77286eb1461079f578063ee4f5a94146107c1576102f4565b8063d3d862d114610729578063d46950281461073c578063e25cabf71461075c576102f4565b8063d001c5dc116100c8578063d001c5dc146106f0578063d186037f14610703578063d363790514610716576102f4565b8063ca49f47c146106ac578063cafd3a07146106cf576102f4565b8063a6627e9f11610145578063bbb2dcf61161011f578063bbb2dcf614610661578063bc03f96414610683578063c26cfecd146106a4576102f4565b8063a6627e9f14610618578063acaedc741461062b578063b43cffe11461064e576102f4565b8063a070cac811610176578063a070cac8146105d2578063a0901e51146105e5578063a5cd62ba146105f8576102f4565b80639a7e75261461058b5780639eadc835146105ae576102f4565b80634dfdac201161024a5780637914b2ec116101fe5780637b66ad34116101d85780637b66ad34146105445780637d727512146105655780638f4ce47914610578576102f4565b80637914b2ec146104f05780637982653e1461051157806379c9c42614610531576102f4565b806363eb39921161022f57806363eb39921461049857806365129042146104ab578063750bdb30146104cd576102f4565b80634dfdac2014610458578063590aa87514610478576102f4565b8063314853ff116102ac5780633db6dc61116102865780633db6dc61146103ff578063459be5e21461042257806346eb65cb14610443576102f4565b8063314853ff146103a8578063327d3054146103ca57806332aae3ad146103dd576102f4565b80630d7b7d76116102dd5780630d7b7d7614610345578063165979e1146103665780632322cf7614610388576102f4565b806302d0aec3146102f957806304a5618a14610323575b600080fd5b61030c610307366004614a21565b6107e3565b60405161031a92919061535e565b60405180910390f35b610336610331366004614a21565b61083f565b60405161031a93929190615488565b610358610353366004614603565b6108ba565b60405161031a92919061530c565b610379610374366004614a21565b6108dc565b60405161031a939291906155c3565b61039b610396366004614603565b610939565b60405161031a91906152c9565b6103bb6103b6366004614a21565b610961565b60405161031a93929190615333565b6103586103d8366004614a21565b6109a8565b6103f06103eb366004614a21565b6109ea565b60405161031a93929190615539565b61041261040d366004614a21565b610a3d565b60405161031a94939291906152d2565b610435610430366004614a21565b610a87565b60405161031a9291906155ac565b610456610451366004614a21565b610add565b005b61046b61046636600461452a565b610c5f565b60405161031a9190615263565b61048b610486366004614341565b610ce2565b60405161031a91906154e8565b61048b6104a6366004614647565b610d52565b6104be6104b9366004614a21565b610dc8565b60405161031a9392919061502f565b6104e06104db366004614a21565b610e02565b60405161031a94939291906153b3565b6105036104fe366004614a21565b610e99565b60405161031a929190615390565b61052461051f366004614ab8565b610ed1565b60405161031a91906155de565b61039b61053f366004614bc0565b61118c565b610557610552366004614a21565b611215565b60405161031a929190615015565b61039b610573366004614603565b61124d565b610503610586366004614a21565b6118a4565b61059e610599366004614a21565b61191a565b60405161031a94939291906155f2565b6105c16105bc366004614a21565b61197b565b60405161031a9594939291906153ef565b61039b6105e0366004614b67565b611a0c565b61046b6105f33660046146c9565b611a8d565b61060b6106063660046146fc565b611b06565b60405161031a919061517b565b61048b61062636600461469e565b611bc9565b61063e610639366004614a21565b611c22565b60405161031a94939291906150d7565b61048b61065c366004614578565b611c5e565b61067461066f366004614a21565b611cd6565b60405161031a939291906154b3565b610696610691366004614a21565b611d50565b60405161031a92919061531a565b61039b611d89565b6106bf6106ba366004614a21565b611d8f565b60405161031a9493929190615445565b6106e26106dd366004614a21565b611e19565b60405161031a929190615629565b61046b6106fe36600461452a565b611e67565b61039b610711366004614603565b611ed5565b610524610724366004614ab8565b6126c7565b61048b6107373660046147cd565b612a77565b61074f61074a366004614a21565b612a96565b60405161031a919061537b565b61076f61076a366004614776565b612b91565b60405161031a939291906151c8565b61079161078c36600461452a565b612cc9565b60405161031a9291906152a4565b6107b26107ad366004614b10565b612ce2565b60405161031a939291906156db565b6107d46107cf366004614a21565b612fa4565b60405161031a93929190615582565b6000806107f7836107f2612fe1565b613005565b600061081060048551866130459092919063ffffffff16565b80602001905161082391908101906149d4565b909350905060ff8116600681111561083757fe5b915050915091565b60008080610853848263ffffffff61308816565b92506001600160e01b0319831663012b8bc960e11b1461088e5760405162461bcd60e51b8152600401610885906156a4565b60405180910390fd5b61089f84601063ffffffff6130bc16565b91506108b284602463ffffffff6130ef16565b929491935050565b6000806108c7848461124d565b91506108d38484611ed5565b90509250929050565b60008060006108ed846107f26130fb565b600061090660048651876130459092919063ffffffff16565b8060200190516109199190810190614d92565b9094509250905060ff8116600281111561092f57fe5b9350509193909250565b600080600061094885856108ba565b91509150610956828261311f565b925050505b92915050565b6000606080610972846107f2613135565b835161098890859060049063ffffffff61304516565b80602001905161099b9190810190614974565b9196909550909350915050565b6000806109b7836107f2613159565b82516109cd90849060049063ffffffff61304516565b8060200190516109e09190810190614916565b9094909350915050565b60008060606109fb846107f261317d565b6000610a1460048651876130459092919063ffffffff16565b806020019051610a279190810190614d52565b9094509250905060ff8116600181111561092f57fe5b600080606080610a4f856107f26131a1565b8451610a6590869060049063ffffffff61304516565b806020019051610a7891908101906148d2565b92989197509550909350915050565b600080610a96836107f26131c5565b6000610aaf60048551866130459092919063ffffffff16565b806020019051610ac29190810190614c90565b9250905060ff81166003811115610ad557fe5b925050915091565b6000610aef828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610b3357610b2c826118a4565b5050610c5b565b6001600160e01b0319811663012b8bc960e11b1415610b5d57610b558261083f565b505050610c5b565b6001600160e01b031981167fa7cb5fb7000000000000000000000000000000000000000000000000000000001415610ba257610b988261197b565b5050505050610c5b565b6001600160e01b031981166394cfcdd760e01b1415610bc457610b5582611cd6565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415610c0857610bff82611d8f565b50505050610c5b565b6001600160e01b031981167fdc1600f3000000000000000000000000000000000000000000000000000000001415610c4357610bff82610e02565b60405162461bcd60e51b8152600401610885906156a4565b5050565b606060008251905080604051908082528060200260200182016040528015610c91578160200160208202803883390190505b50915060005b818114610cda57610cbb85858381518110610cae57fe5b6020026020010151611ed5565b838281518110610cc757fe5b6020908102919091010152600101610c97565b505092915050565b6040516060907ff47261b00000000000000000000000000000000000000000000000000000000090610d18908490602401615001565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b919050565b6040516060907fc339d10a0000000000000000000000000000000000000000000000000000000090610d8c908690869086906024016150a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915290505b9392505050565b6000806000610dd9846107f26131e9565b8351610def90859060049063ffffffff61304516565b80602001905161099b91908101906143f8565b600080806060610e18858363ffffffff61308816565b93506001600160e01b031984167fdc1600f30000000000000000000000000000000000000000000000000000000014610e635760405162461bcd60e51b8152600401610885906156a4565b8451610e7990869060049063ffffffff61320d16565b806020019051610e8c9190810190614396565b9597919650949350915050565b600080610ea8836107f261328d565b8251610ebe90849060049063ffffffff61304516565b8060200190516109e091908101906149f8565b6000610edb613f0c565b610f6c8584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b505afa158015610f42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f669190810190614c78565b3a6132b1565b60408051600280825260608281019093529293509091816020015b6060815260200190600190039081610f8757505060408051600280825260608083018452939450909160208301908038833950506040805160028082526060808301845294955090925090602083019080388339505060408051600280825260608083018452949550909250906020830190803883390190505090508861014001518460008151811061101657fe5b602002602001018190525088600001518360008151811061103357fe5b6001600160a01b039283166020918202929092010152881615611056578761106c565b73377f698c4c287018d09b516f415317aec59193325b8260008151811061107957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460000151816000815181106110ab57fe5b602002602001018181525050886101800151846001815181106110ca57fe5b60200260200101819052508860000151836001815181106110e757fe5b6001600160a01b03928316602091820292909201015260408a01511615611112578860400151611128565b73377f698c4c287018d09b516f415317aec59193325b8260018151811061113557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160018151811061116757fe5b60200260200101818152505061117f84848484613328565b9998505050505050505050565b600061120d846112086040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b61353d565b949350505050565b600080611224836107f2613551565b825161123a90849060049063ffffffff61304516565b8060200190516109e0919081019061435d565b600080611260838263ffffffff61308816565b90506001600160e01b031981167ff47261b00000000000000000000000000000000000000000000000000000000014156112bb5760006112a784601063ffffffff6130bc16565b90506112b38186613575565b92505061189d565b6001600160e01b0319811663012b8bc960e11b1415611413576000806112e08561083f565b6040519194509250606091507f6352211e000000000000000000000000000000000000000000000000000000009061131c9084906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b03168360405161136d9190614fe5565b600060405180830381855afa9150503d80600081146113a8576040519150601f19603f3d011682016040523d82523d6000602084013e6113ad565b606091505b509150915060008280156113c2575081516020145b6113cd5760006113de565b6113de82600c63ffffffff6130bc16565b9050896001600160a01b0316816001600160a01b031614611400576000611403565b60015b60ff16975050505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156116035760006060806114538661197b565b5081519296509094509250905060005b8181146115f95782818151811061147657fe5b60200260200101516000141561148b576115f1565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b908790859081106114bf57fe5b60200260200101516040516024016114d892919061510b565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060876001600160a01b0316836040516115299190614fe5565b600060405180830381855afa9150503d8060008114611564576040519150601f19603f3d011682016040523d82523d6000602084013e611569565b606091505b5091509150600082801561157e575081516020145b61158957600061159a565b61159a82600063ffffffff6130ef16565b905060008786815181106115aa57fe5b602002602001015182816115ba57fe5b049050806115d65760009b50505050505050505050505061095b565b8b8110806115e257508b155b156115eb57809b505b50505050505b600101611463565b505050505061189d565b6001600160e01b031981167fc339d10a000000000000000000000000000000000000000000000000000000001415611721576040516060907fa85e59e40000000000000000000000000000000000000000000000000000000090611672908690600090819081906024016154fb565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260045491519092506000916001600160a01b0316906116c4908490614fe5565b600060405180830381855afa9150503d80600081146116ff576040519150601f19603f3d011682016040523d82523d6000602084013e611704565b606091505b5050905080611714576000611718565b6000195b9350505061189d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156117c85760008061175f85610e02565b50925092505061176d613678565b6001600160a01b0316826001600160a01b031614801561179a57506005546001600160a01b038281169116145b156117c15760006117b26117ac613690565b88613575565b90506117bd816136a8565b9450505b505061189d565b6001600160e01b031981166394cfcdd760e01b141561189d576060806117ed85611cd6565b80519194509250905060005b8181146118985783818151811061180c57fe5b60200260200101516000141561182157611890565b60006118408985848151811061183357fe5b602002602001015161124d565b9050600085838151811061185057fe5b6020026020010151828161186057fe5b0490508061187857600097505050505050505061095b565b87811080611884575087155b1561188d578097505b50505b6001016117f9565b505050505b5092915050565b6000806118b7838263ffffffff61308816565b91506001600160e01b031982167ff47261b000000000000000000000000000000000000000000000000000000000146119025760405162461bcd60e51b8152600401610885906156a4565b61191383601063ffffffff6130bc16565b9050915091565b6000806000606061192d856107f26138a6565b600061194660048751886130459092919063ffffffff16565b8060200190516119599190810190614cf4565b91965094509250905060ff8116600681111561197157fe5b9450509193509193565b60008060608080611992868563ffffffff61308816565b94506001600160e01b031985167fa7cb5fb700000000000000000000000000000000000000000000000000000000146119dd5760405162461bcd60e51b8152600401610885906156a4565b505050506024828101516044840151606485015160848601519496929591820184019490820184019391010190565b600061120d84611a886040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876134e6565b6138ca565b6060808251604051908082528060200260200182016040528015611abb578160200160208202803883390190505b50905060005b8351811461189d57838181518110611ad557fe5b60200260200101516001600160a01b031631828281518110611af357fe5b6020908102919091010152600101611ac1565b606060008451905080604051908082528060200260200182016040528015611b38578160200160208202803883390190505b50915060005b818114611bc057611b89868281518110611b5457fe5b6020026020010151868381518110611b6857fe5b6020026020010151868481518110611b7c57fe5b60200260200101516126c7565b838281518110611b9557fe5b60200260200101906004811115611ba857fe5b90816004811115611bb557fe5b905250600101611b3e565b50509392505050565b60405160609063012b8bc960e11b90611be8908590859060240161510b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905092915050565b60006060806060611c35856107f26138d9565b8451611c4b90869060049063ffffffff61304516565b806020019051610a789190810190614492565b6040516060907fa7cb5fb70000000000000000000000000000000000000000000000000000000090611c9a908790879087908790602401615053565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091529050949350505050565b6000606080611ceb848463ffffffff61308816565b92506001600160e01b031983166394cfcdd760e01b14611d1d5760405162461bcd60e51b8152600401610885906156a4565b8351611d3390859060049063ffffffff61320d16565b806020019051611d469190810190614802565b9395909450915050565b60006060611d60836107f26138fd565b8251611d7690849060049063ffffffff61304516565b8060200190516109e09190810190614939565b60075481565b600080606081611da5858263ffffffff61308816565b93506001600160e01b031984167fc339d10a0000000000000000000000000000000000000000000000000000000014611df05760405162461bcd60e51b8152600401610885906156a4565b8451611e0690869060049063ffffffff61320d16565b806020019051610e8c919081019061443a565b600080611e28836107f2613921565b6000611e4160048551866130459092919063ffffffff16565b806020019051611e549190810190614c90565b9250905060ff81166001811115610ad557fe5b606060008251905080604051908082528060200260200182016040528015611e99578160200160208202803883390190505b50915060005b818114610cda57611eb68585838151811061183357fe5b838281518110611ec257fe5b6020908102919091010152600101611e9f565b600080611ee8838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b1415611fb857606080611f0f85611cd6565b80519194509250905060005b818114611fad57838181518110611f2e57fe5b602002602001015160001415611f4357611fa5565b6000611f5589858481518110610cae57fe5b90506000858381518110611f6557fe5b60200260200101518281611f7557fe5b04905080611f8d57600097505050505050505061095b565b87811080611f99575087155b15611fa2578097505b50505b600101611f1b565b5061095b9350505050565b6001600160e01b031981167ff47261b000000000000000000000000000000000000000000000000000000000141561210e576000611ffd84601063ffffffff6130bc16565b6001546040519192506060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916120439189916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b0316836040516120949190614fe5565b600060405180830381855afa9150503d80600081146120cf576040519150601f19603f3d011682016040523d82523d6000602084013e6120d4565b606091505b50915091508180156120e7575080516020145b6120f2576000612103565b61210381600063ffffffff6130ef16565b95505050505061189d565b6001600160e01b0319811663012b8bc960e11b1415612373576000806121338561083f565b600254604051929550909350606092507fe985e9c5000000000000000000000000000000000000000000000000000000009161217f918a916001600160a01b0390911690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060846001600160a01b0316836040516121d09190614fe5565b600060405180830381855afa9150503d806000811461220b576040519150601f19603f3d011682016040523d82523d6000602084013e612210565b606091505b509150915081158061222457508051602014155b80612240575061223b81600063ffffffff6130ef16565b600114155b15612364576040516060907f081812fc000000000000000000000000000000000000000000000000000000009061227b9087906024016152c9565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050509050856001600160a01b0316816040516122c89190614fe5565b600060405180830381855afa9150503d8060008114612303576040519150601f19603f3d011682016040523d82523d6000602084013e612308565b606091505b50909350915082801561231c575081516020145b801561234b57506002546001600160a01b031661234083600c63ffffffff6130bc16565b6001600160a01b0316145b612356576000612359565b60015b60ff169750506115f9565b6000199650505050505061189d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156124d35760006123b08461197b565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926123fa925089916001600160a01b031690602401615015565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060836001600160a01b03168360405161244b9190614fe5565b600060405180830381855afa9150503d8060008114612486576040519150601f19603f3d011682016040523d82523d6000602084013e61248b565b606091505b509150915081801561249e575080516020145b80156124ba57506124b681600063ffffffff6130ef16565b6001145b6124c5576000612103565b60001995505050505061189d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561250f57600019915061189d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561189d5760008061254d85610e02565b50925092505061255b613678565b6001600160a01b0316826001600160a01b031614801561258857506005546001600160a01b038281169116145b156126be576005546040516060917fdd62ed3e00000000000000000000000000000000000000000000000000000000916125d2918a916001600160a01b0390911690602401615015565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905060006060612612613690565b6001600160a01b0316836040516126299190614fe5565b600060405180830381855afa9150503d8060008114612664576040519150601f19603f3d011682016040523d82523d6000602084013e612669565b606091505b5091509150600082801561267e575081516020145b61268957600061269a565b61269a82600063ffffffff6130ef16565b905060001981146126b3576126ae816136a8565b6126b7565b6000195b9750505050505b50505092915050565b60006126d1613f0c565b6127248584600660009054906101000a90046001600160a01b03166001600160a01b0316631ce4c78b6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2e57600080fd5b60408051600480825260a0820190925291925060609190816020015b606081526020019060019003908161274057505060408051600480825260a082019092529192506060919060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339505060408051600480825260a08201909252929350606092915060208201608080388339019050509050886101600151846000815181106127d657fe5b602002602001018190525087836000815181106127ef57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505088600001518260008151811061282157fe5b60200260200101906001600160a01b031690816001600160a01b031681525050868160008151811061284f57fe5b6020026020010181815250508861014001518460018151811061286e57fe5b602002602001018190525088600001518360018151811061288b57fe5b6001600160a01b0392831660209182029290920101528816156128ae57876128c4565b73377f698c4c287018d09b516f415317aec59193325b826001815181106128d157fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084600001518160018151811061290357fe5b602002602001018181525050886101a001518460028151811061292257fe5b6020026020010181905250878360028151811061293b57fe5b6001600160a01b03928316602091820292909201015260408a0151161561296657886040015161297c565b73377f698c4c287018d09b516f415317aec59193325b8260028151811061298957fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508460600151816002815181106129bb57fe5b602002602001018181525050886101800151846003815181106129da57fe5b60200260200101819052508860000151836003815181106129f757fe5b6001600160a01b03928316602091820292909201015260408a01511615612a22578860400151612a38565b73377f698c4c287018d09b516f415317aec59193325b82600381518110612a4557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505084604001518160038151811061116757fe5b6040516060906394cfcdd760e01b90611be89085908590602401615276565b6000612aa8828263ffffffff61308816565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001480612af257506001600160e01b0319811663012b8bc960e11b145b80612b2657506001600160e01b031981167fa7cb5fb700000000000000000000000000000000000000000000000000000000145b80612b4157506001600160e01b031981166394cfcdd760e01b145b80612b7557506001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000145b610d4d5760405162461bcd60e51b8152600401610885906156a4565b606080606060008551905080604051908082528060200260200182016040528015612bd657816020015b612bc3613f3b565b815260200190600190039081612bbb5790505b50935080604051908082528060200260200182016040528015612c03578160200160208202803883390190505b50925080604051908082528060200260200182016040528015612c30578160200160208202803883390190505b50915060005b818114612cc057612c6d878281518110612c4c57fe5b6020026020010151878381518110612c6057fe5b6020026020010151612ce2565b8751889085908110612c7b57fe5b60200260200101878581518110612c8e57fe5b60200260200101878681518110612ca157fe5b9315156020948502919091019093019290925291905252600101612c36565b50509250925092565b606080612cd68484611e67565b91506108d38484610c5f565b612cea613f3b565b6006546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815260009182916001600160a01b0390911690639d3fa4b990612d389088906004016156ff565b60606040518083038186803b158015612d5057600080fd5b505afa158015612d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d889190810190614a70565b85516006546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f90612dda9089908990600401615712565b60206040518083038186803b158015612df257600080fd5b505afa158015612e06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612e2a91908101906148b2565b91506000612e3d82886101400151610939565b60a088015160c08901516101808a01516101408b015193945091929091600091612e6c9163ffffffff61394516565b15612e9957612e9284612e8c848d6080015161396a90919063ffffffff16565b85613986565b9050612ef2565b81612ead57612e92848b6080015185613986565b6000612ebe868c6101800151610939565b90506000612ed1868d6080015187613986565b90506000612ee0838688613986565b9050612eec828261311f565b93505050505b612f12612f0c8960400151856139a890919063ffffffff16565b8261311f565b96506004612f258b8c602001518a610ed1565b6004811115612f3057fe5b14612f3c576000612f3e565b865b9650612f4e8a61016001516139c7565b612f5757600096505b60e08a015115801590612f755750612f738a6101a001516139c7565b155b15612f7f57600096505b600388516006811115612f8e57fe5b14612f9857600096505b50505050509250925092565b6000806000612fb5846107f2613ab1565b6000612fce60048651876130459092919063ffffffff16565b8060200190516109199190810190614cbd565b7ffdb6ca8d0000000000000000000000000000000000000000000000000000000090565b6000613012836000613088565b90506001600160e01b0319808216908316146130405760405162461bcd60e51b81526004016108859061566d565b505050565b6060818311156130635761306361305e60008585613ad5565b613af4565b835182111561307c5761307c61305e6001848751613ad5565b50819003910190815290565b600081600401835110156130a9576130a961305e6003855185600401613ad5565b5001602001516001600160e01b03191690565b600081601401835110156130dd576130dd61305e6004855185601401613ad5565b5001601401516001600160a01b031690565b6000610dc18383613afc565b7f18e4b1410000000000000000000000000000000000000000000000000000000090565b600081831061312e5781610dc1565b5090919050565b7f4678472b0000000000000000000000000000000000000000000000000000000090565b7fb6555d6f0000000000000000000000000000000000000000000000000000000090565b7f488219a60000000000000000000000000000000000000000000000000000000090565b7f1b8388f70000000000000000000000000000000000000000000000000000000090565b7fe94a7ed00000000000000000000000000000000000000000000000000000000090565b7f4ad312750000000000000000000000000000000000000000000000000000000090565b6060818311156132265761322661305e60008585613ad5565b835182111561323f5761323f61305e6001848751613ad5565b8282036040519080825280601f01601f19166020018201604052801561326c576020820181803883390190505b509050610dc161327b82613b26565b8461328587613b26565b018351613b2c565b7f11c7b7200000000000000000000000000000000000000000000000000000000090565b6132b9613f0c565b6020810184905260a085015160808601516132d5918691613bd1565b815260a085015160c08601516132ec918691613bd1565b604082015260a085015160e0860151613306918691613bd1565b606082015261331b828463ffffffff613c0516565b6080820152949350505050565b6040516000906060907fb04fbddd0000000000000000000000000000000000000000000000000000000090613367908890889088908890602401615124565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925260065491519092506060916001600160a01b0316906133b9908490614fe5565b6000604051808303816000865af19150503d80600081146133f6576040519150601f19603f3d011682016040523d82523d6000602084013e6133fb565b606091505b50915060009050613412828263ffffffff61308816565b905061341c61317d565b6001600160e01b03198281169116141561345957600061343b836109ea565b5091505060ff8116600481111561344e57fe5b94505050505061120d565b613461613135565b6001600160e01b03198281169116141561349457600061348083610961565b509091505060ff8116600481111561344e57fe5b815160208301207ff43f26ea5a94b478394a975e856464913dc1a8a1ca70939d974aa7c238aa0ce014156134ce576004935050505061120d565b60405162461bcd60e51b815260040161088590615636565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b6000610dc18261354c85613c36565b613cb1565b7fa15c0d060000000000000000000000000000000000000000000000000000000090565b6040516000906060907f70a0823100000000000000000000000000000000000000000000000000000000906135ae908590602401615001565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050905060006060856001600160a01b0316836040516135ff9190614fe5565b600060405180830381855afa9150503d806000811461363a576040519150601f19603f3d011682016040523d82523d6000602084013e61363f565b606091505b5091509150818015613652575080516020145b61365d57600061366e565b61366e81600063ffffffff6130ef16565b9695505050505050565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b6000806136b3613690565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156136ed57600080fd5b505af1158015613701573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506137259190810190614a54565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561376457600080fd5b505af1158015613778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061379c9190810190614c78565b421161381a57816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156137dd57600080fd5b505af11580156137f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506138159190810190614c78565b61388d565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561385557600080fd5b505af1158015613869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061388d9190810190614c78565b905061120d816b033b2e3c9fd0803ce800000086613986565b7f7e5a23180000000000000000000000000000000000000000000000000000000090565b6000610dc18261354c85613ceb565b7f5bd0428d0000000000000000000000000000000000000000000000000000000090565b7f20d11f610000000000000000000000000000000000000000000000000000000090565b7ff59851840000000000000000000000000000000000000000000000000000000090565b600081518351148015610dc15750508051602091820120825192909101919091201490565b600082820183811015610dc157610dc161305e60008686613da4565b600061120d8361399c868563ffffffff613c0516565b9063ffffffff613dc316565b6000828211156139c1576139c161305e60028585613da4565b50900390565b600060208251816139d457fe5b066004146139e457506000610d4d565b60006139f6838263ffffffff61308816565b90506001600160e01b031981166394cfcdd760e01b14613a1a576001915050610d4d565b606080613a2685611cd6565b80519194509250905060005b818114613aa4576000613a626000858481518110613a4c57fe5b602002602001015161308890919063ffffffff16565b90506001600160e01b0319811663012b8bc960e11b1415613a9b57613a878483613ded565b15613a9b5760009650505050505050610d4d565b50600101613a32565b5060019695505050505050565b7fe53c76c80000000000000000000000000000000000000000000000000000000090565b6060632800659560e01b848484604051602401610d8c939291906155d0565b805160208201fd5b60008160200183511015613b1d57613b1d61305e6005855185602001613ad5565b50016020015190565b60200190565b6020811015613b56576001816020036101000a038019835116818551168082178652505050613040565b82821415613b6357613040565b82821115613b9d5760208103905080820181840181515b82851015613b95578451865260209586019590940193613b7a565b905250613040565b60208103905080820181840183515b81861215613bc85782518252601f199283019290910190613bac565b85525050505050565b6000613bde848484613e50565b15613bf157613bf161305e858585613eb6565b61120d8361399c868563ffffffff613c0516565b600082613c145750600061095b565b82820282848281613c2157fe5b0414610dc157610dc161305e60018686613da4565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a753493909290916020871015613d3757fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b606063e946c1bb60e01b848484604051602401610d8c93929190615561565b600081613dd957613dd961305e60038585613da4565b6000828481613de457fe5b04949350505050565b8151600090600183015b81811015610cda57613e38858281518110613e0e57fe5b6020026020010151868681518110613e2257fe5b602002602001015161394590919063ffffffff16565b15613e485760019250505061095b565b600101613df7565b600082613e6257613e6261305e613ed5565b811580613e6d575083155b15613e7a57506000610dc1565b60008380613e8457fe5b8584099050613e99858463ffffffff613c0516565b613eab826103e863ffffffff613c0516565b101595945050505050565b606063339f3de260e01b848484604051602401610d8c93929190615737565b60408051808201909152600481527fa791837c00000000000000000000000000000000000000000000000000000000602082015290565b6040518060a0016040528060008152602001600081526020016000815260200160008152602001600081525090565b6040805160608101909152806000815260006020820181905260409091015290565b803561095b81615813565b600082601f830112613f78578081fd5b8135613f8b613f8682615774565b61574d565b818152915060208083019084810181840286018201871015613fac57600080fd5b60005b84811015611898578135613fc281615813565b84529282019290820190600101613faf565b600082601f830112613fe4578081fd5b8151613ff2613f8682615774565b8181529150602080830190840160005b8381101561402f5761401a876020845189010161419b565b83526020928301929190910190600101614002565b5050505092915050565b600082601f830112614049578081fd5b8135614057613f8682615774565b8181529150602080830190840160005b8381101561402f5761407f876020843589010161414d565b83526020928301929190910190600101614067565b600082601f8301126140a4578081fd5b81356140b2613f8682615774565b8181529150602080830190840160005b8381101561402f576140da87602084358901016141e1565b835260209283019291909101906001016140c2565b600082601f8301126140ff578081fd5b813561410d613f8682615774565b81815291506020808301908481018184028601820187101561412e57600080fd5b60005b8481101561189857813584529282019290820190600101614131565b600082601f83011261415d578081fd5b813561416b613f8682615794565b915080825283602082850101111561418257600080fd5b8060208401602084013760009082016020015292915050565b600082601f8301126141ab578081fd5b81516141b9613f8682615794565b91508082528360208285010111156141d057600080fd5b61189d8160208401602086016157b8565b60006101c08083850312156141f4578182fd5b6141fd8161574d565b91505061420a8383613f5d565b81526142198360208401613f5d565b602082015261422b8360408401613f5d565b604082015261423d8360608401613f5d565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561429f57600080fd5b6142ab8683870161414d565b838501526101609250828501359150808211156142c757600080fd5b6142d38683870161414d565b838501526101809250828501359150808211156142ef57600080fd5b6142fb8683870161414d565b838501526101a092508285013591508082111561431757600080fd5b506143248582860161414d565b82840152505092915050565b805160ff8116811461095b57600080fd5b600060208284031215614352578081fd5b8135610dc181615813565b6000806040838503121561436f578081fd5b825161437a81615813565b602084015190925061438b81615813565b809150509250929050565b6000806000606084860312156143aa578081fd5b83516143b581615813565b60208501519093506143c681615813565b604085015190925067ffffffffffffffff8111156143e2578182fd5b6143ee8682870161419b565b9150509250925092565b60008060006060848603121561440c578081fd5b835161441781615813565b602085015190935061442881615813565b80925050604084015190509250925092565b60008060006060848603121561444e578081fd5b835161445981615813565b602085015190935067ffffffffffffffff811115614475578182fd5b6144818682870161419b565b925050604084015190509250925092565b600080600080608085870312156144a7578182fd5b84516144b281615813565b602086015190945067ffffffffffffffff808211156144cf578384fd5b6144db8883890161419b565b945060408701519150808211156144f0578384fd5b6144fc8883890161419b565b93506060870151915080821115614511578283fd5b5061451e8782880161419b565b91505092959194509250565b6000806040838503121561453c578182fd5b823561454781615813565b9150602083013567ffffffffffffffff811115614562578182fd5b61456e85828601614039565b9150509250929050565b6000806000806080858703121561458d578182fd5b843561459881615813565b9350602085013567ffffffffffffffff808211156145b4578384fd5b6145c0888389016140ef565b945060408701359150808211156145d5578384fd5b6145e1888389016140ef565b935060608701359150808211156145f6578283fd5b5061451e8782880161414d565b60008060408385031215614615578182fd5b823561462081615813565b9150602083013567ffffffffffffffff81111561463b578182fd5b61456e8582860161414d565b60008060006060848603121561465b578081fd5b833561466681615813565b9250602084013567ffffffffffffffff811115614681578182fd5b61468d8682870161414d565b925050604084013590509250925092565b600080604083850312156146b0578182fd5b82356146bb81615813565b946020939093013593505050565b6000602082840312156146da578081fd5b813567ffffffffffffffff8111156146f0578182fd5b61120d84828501613f68565b600080600060608486031215614710578081fd5b833567ffffffffffffffff80821115614727578283fd5b61473387838801614094565b94506020860135915080821115614748578283fd5b61475487838801613f68565b93506040860135915080821115614769578283fd5b506143ee868287016140ef565b60008060408385031215614788578182fd5b823567ffffffffffffffff8082111561479f578384fd5b6147ab86838701614094565b935060208501359150808211156147c0578283fd5b5061456e85828601614039565b600080604083850312156147df578182fd5b823567ffffffffffffffff808211156147f6578384fd5b6147ab868387016140ef565b60008060408385031215614814578182fd5b825167ffffffffffffffff8082111561482b578384fd5b81850186601f82011261483c578485fd5b8051925061484c613f8684615774565b80848252602080830192508084018a82838902870101111561486c578889fd5b8894505b8685101561488e578051845260019490940193928101928101614870565b5088015190965093505050808211156148a5578283fd5b5061456e85828601613fd4565b6000602082840312156148c3578081fd5b81518015158114610dc1578182fd5b600080600080608085870312156148e7578182fd5b8451935060208501516148f981615813565b604086015190935067ffffffffffffffff808211156144f0578384fd5b60008060408385031215614928578182fd5b505080516020909101519092909150565b6000806040838503121561494b578182fd5b82519150602083015167ffffffffffffffff811115614968578182fd5b61456e8582860161419b565b600080600060608486031215614988578081fd5b83519250602084015167ffffffffffffffff808211156149a6578283fd5b6149b28783880161419b565b935060408601519150808211156149c7578283fd5b506143ee8682870161419b565b600080604083850312156149e6578182fd5b82519150602083015161438b81615828565b60008060408385031215614a0a578182fd5b82516001600160e01b03198116811461437a578283fd5b600060208284031215614a32578081fd5b813567ffffffffffffffff811115614a48578182fd5b61120d8482850161414d565b600060208284031215614a65578081fd5b8151610dc181615813565b600060608284031215614a81578081fd5b614a8b606061574d565b825160078110614a99578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614acc578081fd5b833567ffffffffffffffff811115614ae2578182fd5b614aee868287016141e1565b9350506020840135614aff81615813565b929592945050506040919091013590565b60008060408385031215614b22578182fd5b823567ffffffffffffffff80821115614b39578384fd5b614b45868387016141e1565b93506020850135915080821115614b5a578283fd5b5061456e8582860161414d565b600080600060608486031215614b7b578081fd5b833567ffffffffffffffff811115614b91578182fd5b614b9d868287016141e1565b935050602084013591506040840135614bb581615813565b809150509250925092565b600080600060608486031215614bd4578081fd5b833567ffffffffffffffff80821115614beb578283fd5b81860160a08189031215614bfd578384fd5b614c0760a061574d565b9250803583526020810135602084015260408101356040840152614c2e8860608301613f5d565b6060840152608081013582811115614c44578485fd5b614c508982840161414d565b608085015250919450505060208401359150614c6f8560408601613f5d565b90509250925092565b600060208284031215614c89578081fd5b5051919050565b60008060408385031215614ca2578182fd5b8251614cad81615828565b6020939093015192949293505050565b600080600060608486031215614cd1578081fd5b8351614cdc81615828565b602085015160408601519194509250614bb581615813565b60008060008060808587031215614d09578182fd5b614d138686614330565b9350602085015192506040850151614d2a81615813565b606086015190925067ffffffffffffffff811115614d46578182fd5b61451e8782880161419b565b600080600060608486031215614d66578081fd5b614d708585614330565b925060208401519150604084015167ffffffffffffffff8111156143e2578182fd5b600080600060608486031215614da6578081fd5b614db08585614330565b925060208401519150604084015190509250925092565b6001600160a01b03169052565b6000815180845260208401935060208301825b82811015614e0e5781516001600160a01b0316865260209586019590910190600101614de7565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b84811015614e63578284038852614e4d848351614ea0565b6020988901989094509190910190600101614e35565b50919695505050505050565b6000815180845260208401935060208301825b82811015614e0e578151865260209586019590910190600101614e82565b60008151808452614eb88160208601602086016157b8565b601f01601f19169290920160200192915050565b8051614ed781615809565b825260208181015190830152604090810151910152565b60006101c0614efe848451614dc7565b6020830151614f106020860182614dc7565b506040830151614f236040860182614dc7565b506060830151614f366060860182614dc7565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e0850152610100808401518186015250610120808401518186015250610140808401518282870152614f8f83870182614ea0565b91505061016091508184015185820383870152614fac8282614ea0565b925050506101808084015185830382870152614fc88382614ea0565b9150506101a09150818401518582038387015261366e8282614ea0565b60008251614ff78184602087016157b8565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b60006001600160a01b0386168252608060208301526150756080830186614e6f565b82810360408401526150878186614e6f565b83810360608501526150998186614ea0565b98975050505050505050565b60006001600160a01b0385168252606060208301526150c76060830185614ea0565b9050826040830152949350505050565b60006001600160a01b0386168252608060208301526150f96080830186614ea0565b82810360408401526150878186614ea0565b6001600160a01b03929092168252602082015260400190565b6000608082526151376080830187614e18565b82810360208401526151498187614dd4565b838103604085015261515b8187614dd4565b91505082810360608401526151708185614e6f565b979650505050505050565b602080825282518282018190526000918401906040840190835b818110156151bd578351600581106151a957fe5b835260209384019390920191600101615195565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561520b576151f8848351614ecc565b60609390930192908401906001016151e5565b5050508381038285015261521f8187614e6f565b84810360408601528551808252908301915082860190845b81811015615255578251151584529284019291840191600101615237565b509198975050505050505050565b600060208252610dc16020830184614e6f565b6000604082526152896040830185614e6f565b828103602084015261529b8185614e18565b95945050505050565b6000604082526152b76040830185614e6f565b828103602084015261529b8185614e6f565b90815260200190565b60008582526001600160a01b0385166020830152608060408301526152fa6080830185614ea0565b82810360608401526151708185614ea0565b918252602082015260400190565b60008382526040602083015261120d6040830184614ea0565b60008482526060602083015261534c6060830185614ea0565b828103604084015261366e8185614ea0565b8281526040810161536e83615809565b8260208301529392505050565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261366e6080830184614ea0565b60006001600160e01b0319871682526001600160a01b038616602083015260a0604083015261542160a0830186614e6f565b82810360608401526154338186614e6f565b838103608085015261117f8186614ea0565b60006001600160e01b0319861682526001600160a01b0385166020830152608060408301526154776080830185614ea0565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b031985168252606060208301526154d66060830185614e6f565b828103604084015261366e8185614e18565b600060208252610dc16020830184614ea0565b60006080825261550e6080830187614ea0565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6000615544856157e8565b8482528360208301526060604083015261529b6060830184614ea0565b6060810161556e856157f5565b938152602081019290925260409091015290565b6060810161558f856157ff565b93815260208101929092526001600160a01b031660409091015290565b604081016155b9846157f5565b9281526020015290565b6060810161556e856157ff565b606081016008851061556e57fe5b60208101600583106155ec57fe5b91905290565b60006155fd86615809565b8582528460208301526001600160a01b03841660408301526080606083015261366e6080830184614ea0565b604081016155b9846157e8565b60208082526013908201527f554e4b4e4f574e5f52455455524e5f4441544100000000000000000000000000604082015260600190565b6020808252600c908201527f4241445f53454c4543544f520000000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f57524f4e475f50524f58595f4944000000000000000000000000000000000000604082015260600190565b60a081016156e98286614ecc565b8360608301528215156080830152949350505050565b600060208252610dc16020830184614eee565b6000604082526157256040830185614eee565b828103602084015261529b8185614ea0565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561576c57600080fd5b604052919050565b600067ffffffffffffffff82111561578a578081fd5b5060209081020190565b600067ffffffffffffffff8211156157aa578081fd5b50601f01601f191660200190565b60005b838110156157d35781810151838201526020016157bb565b838111156157e2576000848401525b50505050565b600281106157f257fe5b50565b600481106157f257fe5b600381106157f257fe5b600781106157f257fe5b6001600160a01b03811681146157f257600080fd5b60ff811681146157f257600080fdfea365627a7a72315820b8f5e1baee716487ac576e78a6a19b92db1db8535a5a9d8ed8a3c9e3e2968a386c6578706572696d656e74616cf564736f6c63430005100040'; + '0x608060405234801561001057600080fd5b506004361061025c5760003560e01c8063a5cd62ba11610145578063d3637905116100bd578063e4e6e7da1161008c578063ee18599711610071578063ee185997146105b5578063ef3bb097146105bd578063ff84e7cc146105c55761025c565b8063e4e6e7da14610572578063e77286eb146105935761025c565b8063d36379051461050a578063d3d862d11461051d578063d469502814610530578063e25cabf7146105505761025c565b8063c26cfecd11610114578063ca49f47c116100f9578063ca49f47c146104c1578063d001c5dc146104e4578063d186037f146104f75761025c565b8063c26cfecd146104b1578063c82037ef146104b95761025c565b8063a5cd62ba14610449578063a6627e9f14610469578063b43cffe11461047c578063bbb2dcf61461048f5761025c565b80637982653e116101d85780639baf2705116101a75780639eadc8351161018c5780639eadc835146103ff578063a070cac814610423578063a0901e51146104365761025c565b80639baf2705146103e25780639cd01605146103f75761025c565b80637982653e1461037b57806379c9c4261461039b5780637d727512146103ae5780638f4ce479146103c15761025c565b80634dfdac201161022f57806363eb39921161021457806363eb3992146103225780636f83188e14610335578063750bdb30146103585761025c565b80634dfdac20146102e2578063590aa875146103025761025c565b806304a5618a146102615780630d7b7d761461028c5780632322cf76146102ad57806346eb65cb146102cd575b600080fd5b61027461026f36600461406c565b6105cd565b60405161028393929190614abe565b60405180910390f35b61029f61029a366004613b30565b610666565b604051610283929190614ca6565b6102c06102bb366004613b30565b610688565b604051610283919061499b565b6102e06102db36600461406c565b6106b0565b005b6102f56102f0366004613a4b565b610734565b60405161028391906148f3565b610315610310366004613a2f565b6107b7565b6040516102839190614b1e565b610315610330366004613b74565b610866565b61034861034336600461406c565b610919565b6040516102839493929190614bb2565b61036b61036636600461406c565b6109b9565b60405161028394939291906149dc565b61038e610389366004614242565b610a4b565b6040516102839190614b9f565b6102c06103a936600461434a565b610afd565b6102c06103bc366004613b30565b610b7e565b6103d46103cf36600461406c565b611474565b6040516102839291906149b9565b6103ea611507565b604051610283919061465f565b6103ea611516565b61041261040d36600461406c565b611525565b604051610283959493929190614a18565b6102c06104313660046142f1565b6115ca565b6102f5610444366004613bf6565b61164b565b61045c610457366004613cc4565b6116c4565b604051610283919061480c565b610315610477366004613bcb565b61177e565b61031561048a366004613a99565b61182e565b6104a261049d36600461406c565b6118e4565b60405161028393929190614ae9565b6102c0611974565b6103ea61197a565b6104d46104cf36600461406c565b611989565b6040516102839493929190614a7b565b6102f56104f2366004613a4b565b611a1b565b6102c0610505366004613b30565b611a89565b61038e610518366004614242565b612365565b61031561052b366004613d9f565b6123c7565b61054361053e36600461406c565b61241c565b60405161028391906149a4565b61056361055e366004613d48565b6124bf565b60405161028393929190614858565b610585610580366004613a4b565b6125f7565b604051610283929190614976565b6105a66105a136600461429a565b612610565b60405161028393929190614c4a565b6103ea612980565b6103ea61298f565b6103ea61299e565b600080600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a856040518263ffffffff1660e01b81526004016106099190614b1e565b60606040518083038186803b15801561062157600080fd5b505af4158015610635573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506106599190810190613fc2565b9250925092509193909250565b6000806106738484610b7e565b915061067f8484611a89565b90509250929050565b60008060006106978585610666565b915091506106a582826129ad565b925050505b92915050565b6040517f46eb65cb00000000000000000000000000000000000000000000000000000000815273__$d8b635de2bf4a097b4e18b67d0fb68e779$__906346eb65cb90610700908490600401614b1e565b60006040518083038186803b15801561071857600080fd5b505af415801561072c573d6000803e3d6000fd5b505050505b50565b606060008251905080604051908082528060200260200182016040528015610766578160200160208202803883390190505b50915060005b8181146107af576107908585838151811061078357fe5b6020026020010151611a89565b83828151811061079c57fe5b602090810291909101015260010161076c565b505092915050565b6040517f590aa87500000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063590aa8759061080a90859060040161465f565b60006040518083038186803b15801561082257600080fd5b505af4158015610836573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261085e919081019061409f565b90505b919050565b6040517f63eb399200000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__906363eb3992906108bd9087908790879060040161478c565b60006040518083038186803b1580156108d557600080fd5b505af41580156108e9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610911919081019061409f565b949350505050565b60608060608073__$fddee3b26a806429350031cf3481976d2e$__636f83188e866040518263ffffffff1660e01b81526004016109569190614b1e565b60006040518083038186803b15801561096e57600080fd5b505af4158015610982573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa919081019061410d565b93509350935093509193509193565b6000806000606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016109f79190614b1e565b60006040518083038186803b158015610a0f57600080fd5b505af4158015610a23573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613e46565b600080546040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91639caa023b91610aad916001600160a01b0316908890889088906004016147be565b60206040518083038186803b158015610ac557600080fd5b505af4158015610ad9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061091191908101906140ee565b600061091184610b796040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612a1a565b600080610b91838263ffffffff612a2e16565b90506001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415610bec576000610bd884601063ffffffff612a6716565b9050610be48186612a9a565b92505061146d565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415610e055760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401610c589190614b1e565b60606040518083038186803b158015610c7057600080fd5b505af4158015610c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610ca89190810190613fc2565b6040519194509250606091507f6352211e0000000000000000000000000000000000000000000000000000000090610ce490849060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051610d5f9190614643565b600060405180830381855afa9150503d8060008114610d9a576040519150601f19603f3d011682016040523d82523d6000602084013e610d9f565b606091505b50915091506000828015610db4575081516020145b610dbf576000610dd0565b610dd082600c63ffffffff612a6716565b9050896001600160a01b0316816001600160a01b031614610df2576000610df5565b60015b60ff16975050505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156110a157600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b8152600401610e739190614b1e565b60006040518083038186803b158015610e8b57600080fd5b505af4158015610e9f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610ec79190810190613eb0565b5081519296509094509250905060005b81811461109757828181518110610eea57fe5b602002602001015160001415610eff5761108f565b83516060907efdd58e00000000000000000000000000000000000000000000000000000000908b90879085908110610f3357fe5b6020026020010151604051602401610f4c9291906147f3565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060876001600160a01b031683604051610fc79190614643565b600060405180830381855afa9150503d8060008114611002576040519150601f19603f3d011682016040523d82523d6000602084013e611007565b606091505b5091509150600082801561101c575081516020145b611027576000611038565b61103882600063ffffffff612b9216565b9050600087868151811061104857fe5b6020026020010151828161105857fe5b049050806110745760009b5050505050505050505050506106aa565b8b81108061108057508b155b1561108957809b505b50505050505b600101610ed7565b505050505061146d565b6001600160e01b031981167fc339d10a0000000000000000000000000000000000000000000000000000000014156111d4576040516060907fa85e59e4000000000000000000000000000000000000000000000000000000009061111090869060009081908190602401614b31565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199094169390931790925260045491519092506000916001600160a01b031690611177908490614643565b600060405180830381855afa9150503d80600081146111b2576040519150601f19603f3d011682016040523d82523d6000602084013e6111b7565b606091505b50509050806111c75760006111cb565b6000195b9350505061146d565b6001600160e01b031981167fdc1600f30000000000000000000000000000000000000000000000000000000014156112fd5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016112409190614b1e565b60006040518083038186803b15801561125857600080fd5b505af415801561126c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112949190810190613e46565b5092509250506112a2612b9e565b6001600160a01b0316826001600160a01b03161480156112cf57506005546001600160a01b038281169116145b156112f65760006112e76112e1612bb6565b88612a9a565b90506112f281612bce565b9450505b505061146d565b6001600160e01b031981167f94cfcdd700000000000000000000000000000000000000000000000000000000141561146d5760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b81526004016113699190614b1e565b60006040518083038186803b15801561138157600080fd5b505af4158015611395573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113bd9190810190614002565b80519194509250905060005b818114611468578381815181106113dc57fe5b6020026020010151600014156113f157611460565b60006114108985848151811061140357fe5b6020026020010151610b7e565b9050600085838151811061142057fe5b6020026020010151828161143057fe5b049050806114485760009750505050505050506106aa565b87811080611454575087155b1561145d578097505b50505b6001016113c9565b505050505b5092915050565b60008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__638f4ce479846040518263ffffffff1660e01b81526004016114ae9190614b1e565b604080518083038186803b1580156114c557600080fd5b505af41580156114d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506114fd9190810190613e0f565b915091505b915091565b6004546001600160a01b031681565b6000546001600160a01b031681565b600080606080606073__$d8b635de2bf4a097b4e18b67d0fb68e779$__639eadc835876040518263ffffffff1660e01b81526004016115649190614b1e565b60006040518083038186803b15801561157c57600080fd5b505af4158015611590573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115b89190810190613eb0565b939a9299509097509550909350915050565b6000610911846116466040518060400160405280600b81526020017f30782050726f746f636f6c0000000000000000000000000000000000000000008152506040518060400160405280600581526020017f332e302e3000000000000000000000000000000000000000000000000000000081525087876129c3565b612dcc565b6060808251604051908082528060200260200182016040528015611679578160200160208202803883390190505b50905060005b8351811461146d5783818151811061169357fe5b60200260200101516001600160a01b0316318282815181106116b157fe5b602090810291909101015260010161167f565b6000546040517f02cffc4500000000000000000000000000000000000000000000000000000000815260609173__$7a69f714cdde1cb6b62e3c39bc8c94deae$__916302cffc459161172a916001600160a01b039091169088908890889060040161468d565b60006040518083038186803b15801561174257600080fd5b505af4158015611756573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109119190810190613c29565b6040517fa6627e9f00000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063a6627e9f906117d390869086906004016147f3565b60006040518083038186803b1580156117eb57600080fd5b505af41580156117ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611827919081019061409f565b9392505050565b6040517fb43cffe100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063b43cffe190611887908890889088908890600401614746565b60006040518083038186803b15801561189f57600080fd5b505af41580156118b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526118db919081019061409f565b95945050505050565b600060608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6856040518263ffffffff1660e01b81526004016119209190614b1e565b60006040518083038186803b15801561193857600080fd5b505af415801561194c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106599190810190614002565b60065481565b6005546001600160a01b031681565b6000806060600073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63ca49f47c866040518263ffffffff1660e01b81526004016119c79190614b1e565b60006040518083038186803b1580156119df57600080fd5b505af41580156119f3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109aa9190810190613f5a565b606060008251905080604051908082528060200260200182016040528015611a4d578160200160208202803883390190505b50915060005b8181146107af57611a6a8585838151811061140357fe5b838281518110611a7657fe5b6020908102919091010152600101611a53565b600080611a9c838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd7000000000000000000000000000000000000000000000000000000001415611c075760608073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63bbb2dcf6866040518263ffffffff1660e01b8152600401611b0a9190614b1e565b60006040518083038186803b158015611b2257600080fd5b505af4158015611b36573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611b5e9190810190614002565b80519194509250905060005b818114611bfc57838181518110611b7d57fe5b602002602001015160001415611b9257611bf4565b6000611ba48985848151811061078357fe5b90506000858381518110611bb457fe5b60200260200101518281611bc457fe5b04905080611bdc5760009750505050505050506106aa565b87811080611be8575087155b15611bf1578097505b50505b600101611b6a565b506106aa9350505050565b6001600160e01b031981167ff47261b0000000000000000000000000000000000000000000000000000000001415611c68576000611c4c84601063ffffffff612a6716565b600154909150610be490829087906001600160a01b0316612ddb565b6001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415611fb85760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__6304a5618a866040518263ffffffff1660e01b8152600401611cd49190614b1e565b60606040518083038186803b158015611cec57600080fd5b505af4158015611d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611d249190810190613fc2565b600254604051929550909350606092507fe985e9c50000000000000000000000000000000000000000000000000000000091611d70918a916001600160a01b0390911690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060846001600160a01b031683604051611deb9190614643565b600060405180830381855afa9150503d8060008114611e26576040519150601f19603f3d011682016040523d82523d6000602084013e611e2b565b606091505b5091509150811580611e3f57508051602014155b80611e5b5750611e5681600063ffffffff612b9216565b600114155b15611fa9576040516060907f081812fc0000000000000000000000000000000000000000000000000000000090611e9690879060240161499b565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050856001600160a01b031681604051611f0d9190614643565b600060405180830381855afa9150503d8060008114611f48576040519150601f19603f3d011682016040523d82523d6000602084013e611f4d565b606091505b509093509150828015611f61575081516020145b8015611f9057506002546001600160a01b0316611f8583600c63ffffffff612a6716565b6001600160a01b0316145b611f9b576000611f9e565b60015b60ff16975050611097565b6000199650505050505061146d565b6001600160e01b031981167fa7cb5fb70000000000000000000000000000000000000000000000000000000014156121df576040517f9eadc83500000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__90639eadc8359061203d908790600401614b1e565b60006040518083038186803b15801561205557600080fd5b505af4158015612069573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120919190810190613eb0565b5050600354604051929450606093507fe985e9c500000000000000000000000000000000000000000000000000000000926120db925089916001600160a01b031690602401614673565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006060836001600160a01b0316836040516121569190614643565b600060405180830381855afa9150503d8060008114612191576040519150601f19603f3d011682016040523d82523d6000602084013e612196565b606091505b50915091508180156121a9575080516020145b80156121c557506121c181600063ffffffff612b9216565b6001145b6121d05760006121d4565b6000195b95505050505061146d565b6001600160e01b031981167fc339d10a00000000000000000000000000000000000000000000000000000000141561221b57600019915061146d565b6001600160e01b031981167fdc1600f300000000000000000000000000000000000000000000000000000000141561146d5760008073__$d8b635de2bf4a097b4e18b67d0fb68e779$__63750bdb30866040518263ffffffff1660e01b81526004016122879190614b1e565b60006040518083038186803b15801561229f57600080fd5b505af41580156122b3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122db9190810190613e46565b5092509250506122e9612b9e565b6001600160a01b0316826001600160a01b031614801561231657506005546001600160a01b038281169116145b1561235c57600061233b612328612bb6565b60055489906001600160a01b0316612ddb565b905060001981146123545761234f81612bce565b612358565b6000195b9450505b50505092915050565b600080546040517f8dccde0400000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__91638dccde0491610aad916001600160a01b0316908890889088906004016147be565b6040517fd3d862d100000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d3d862d1906117d39086908690600401614906565b6040517fd469502800000000000000000000000000000000000000000000000000000000815260009073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063d46950289061246f908590600401614b1e565b60206040518083038186803b15801561248757600080fd5b505af415801561249b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061085e9190810190613df4565b60608060606000855190508060405190808252806020026020018201604052801561250457816020015b6124f1613467565b8152602001906001900390816124e95790505b50935080604051908082528060200260200182016040528015612531578160200160208202803883390190505b5092508060405190808252806020026020018201604052801561255e578160200160208202803883390190505b50915060005b8181146125ee5761259b87828151811061257a57fe5b602002602001015187838151811061258e57fe5b6020026020010151612610565b87518890859081106125a957fe5b602002602001018785815181106125bc57fe5b602002602001018786815181106125cf57fe5b9315156020948502919091019093019290925291905252600101612564565b50509250925092565b6060806126048484611a1b565b915061067f8484610734565b612618613467565b600080546040517f9d3fa4b900000000000000000000000000000000000000000000000000000000815282916001600160a01b031690639d3fa4b990612662908890600401614c6e565b60606040518083038186803b15801561267a57600080fd5b505afa15801561268e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506126b291908101906141fa565b85516000546040517fa12dcc6f00000000000000000000000000000000000000000000000000000000815292955090916001600160a01b039091169063a12dcc6f906127049089908990600401614c81565b60206040518083038186803b15801561271c57600080fd5b505afa158015612730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506127549190810190613dd4565b9150600061276187612ee5565b90506000612782886101800151896101400151612f0190919063ffffffff16565b156127b7576127b0826127a68a60c001518b60800151612f2690919063ffffffff16565b8a60a00151612f42565b9050612824565b60c08801516127d3576127b08289608001518a60a00151612f42565b60006127e4848a6101800151610688565b905060006127fb848b608001518c60a00151612f42565b90506000612812838c60c001518d60a00151612f42565b905061281e82826129ad565b93505050505b61284861284287604001518a60a00151612f6490919063ffffffff16565b826129ad565b9450600460005460208a01516040517f9caa023b00000000000000000000000000000000000000000000000000000000815273__$7a69f714cdde1cb6b62e3c39bc8c94deae$__92639caa023b926128b3926001600160a01b03909216918e91908c906004016147be565b60206040518083038186803b1580156128cb57600080fd5b505af41580156128df573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061290391908101906140ee565b600481111561290e57fe5b1461291a57600061291c565b845b945061292c886101600151612f83565b61293557600094505b60e0880151158015906129535750612951886101a00151612f83565b155b1561295d57600094505b60038651600681111561296c57fe5b1461297657600094505b5050509250925092565b6001546001600160a01b031681565b6002546001600160a01b031681565b6003546001600160a01b031681565b60008183106129bc5781611827565b5090919050565b8351602094850120835193850193909320604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f815295860194909452928401929092526060830152608082015260a0902090565b600061182782612a2985613138565b6131b3565b60008160040183511015612a5457612a54612a4f60038551856004016131ed565b61325c565b5001602001516001600160e01b03191690565b60008160140183511015612a8857612a88612a4f60048551856014016131ed565b5001601401516001600160a01b031690565b60405160009081906060906001600160a01b038616907f70a082310000000000000000000000000000000000000000000000000000000090612ae090879060240161465f565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612b339190614643565b600060405180830381855afa9150503d8060008114612b6e576040519150601f19603f3d011682016040523d82523d6000602084013e612b73565b606091505b5091509150818015612b86575080516020145b156107af576106a58160005b60006118278383613264565b736b175474e89094c44da98b954eedeac495271d0f90565b7306af07097c9eeb7fd685c692751d5c66db49c21590565b600080612bd9612bb6565b6001600160a01b0316634ba2363a6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c1357600080fd5b505af1158015612c27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612c4b91908101906140d2565b90506000816001600160a01b03166320aba08b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612c8a57600080fd5b505af1158015612c9e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612cc29190810190614402565b4211612d4057816001600160a01b031663c92aecc46040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d0357600080fd5b505af1158015612d17573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612d3b9190810190614402565b612db3565b816001600160a01b0316639f678cca6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612d7b57600080fd5b505af1158015612d8f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612db39190810190614402565b9050610911816b033b2e3c9fd0803ce800000086612f42565b600061182782612a298561328e565b60405160009081906060906001600160a01b038716907fdd62ed3e0000000000000000000000000000000000000000000000000000000090612e239088908890602401614673565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b0319909416939093179092529051612e769190614643565b600060405180830381855afa9150503d8060008114612eb1576040519150601f19603f3d011682016040523d82523d6000602084013e612eb6565b606091505b5091509150818015612ec9575080516020145b15612edc57612ed9816000612b92565b92505b50509392505050565b6000806000612ef384613347565b9150915061091182826129ad565b6000815183511480156118275750508051602091820120825192909101919091201490565b60008282018381101561182757611827612a4f6000868661338a565b600061091183612f58868563ffffffff6133a916565b9063ffffffff6133da16565b600082821115612f7d57612f7d612a4f6002858561338a565b50900390565b60006020825181612f9057fe5b06600414612fa057506000610861565b6000612fb2838263ffffffff612a2e16565b90506001600160e01b031981167f94cfcdd70000000000000000000000000000000000000000000000000000000014612fef576001915050610861565b6040517fbbb2dcf600000000000000000000000000000000000000000000000000000000815260609073__$d8b635de2bf4a097b4e18b67d0fb68e779$__9063bbb2dcf690613042908790600401614b1e565b60006040518083038186803b15801561305a57600080fd5b505af415801561306e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526130969190810190614002565b80519093509150600090505b81811461312c5760006130d260008584815181106130bc57fe5b6020026020010151612a2e90919063ffffffff16565b90506001600160e01b031981167f02571792000000000000000000000000000000000000000000000000000000001415613123576131108483613404565b1561312357600095505050505050610861565b506001016130a2565b50600195945050505050565b608081810151825160208085015160408087015160609788015186519685019690962082517fec69816980a3a3ca4554410e60253953e9ff375ba4536a98adfa15cc7154150881529485019590955290830191909152948101949094526001600160a01b039091169183019190915260a082015260c0902090565b6040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6060632800659560e01b84848460405160240161320c93929190614b91565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b6000816020018351101561328557613285612a4f60058551856020016131ed565b50016020015190565b6101408101516101608201516101808301516101a08401516000937ff80322eb8376aafb64eadf8f0d7623f22130fd9491a221e902b713cb984a7534939092909160208710156132da57fe5b601f1987018051610140890180516101608b0180516101808d0180516101a08f0180519d89528c5160209d8e012087528b519b8d019b909b2084528951998c01999099208152875197909a019690962088526101e085209390945290529190529252919091529050919050565b600080600483610140015151101561336457506000905080611502565b6133778360000151846101400151610b7e565b6114fd8460000151856101400151611a89565b606063e946c1bb60e01b84848460405160240161320c93929190614b6f565b6000826133b8575060006106aa565b828202828482816133c557fe5b041461182757611827612a4f6001868661338a565b6000816133f0576133f0612a4f6003858561338a565b60008284816133fb57fe5b04949350505050565b8151600090600183015b818110156107af5761344f85828151811061342557fe5b602002602001015186868151811061343957fe5b6020026020010151612f0190919063ffffffff16565b1561345f576001925050506106aa565b60010161340e565b6040805160608101909152806000815260006020820181905260409091015290565b80356106aa81614d59565b80516106aa81614d59565b600082601f8301126134af578081fd5b81356134c26134bd82614cdb565b614cb4565b8181529150602080830190848101818402860182018710156134e357600080fd5b60005b848110156114685781356134f981614d59565b845292820192908201906001016134e6565b600082601f83011261351b578081fd5b81356135296134bd82614cdb565b8181529150602080830190840160005b838110156135665761355187602084358901016136fa565b83526020928301929190910190600101613539565b5050505092915050565b600082601f830112613580578081fd5b815161358e6134bd82614cdb565b8181529150602080830190840160005b83811015613566576135b68760208451890101613748565b8352602092830192919091019060010161359e565b600082601f8301126135db578081fd5b81356135e96134bd82614cdb565b8181529150602080830190840160005b8381101561356657613611876020843589010161379d565b835260209283019291909101906001016135f9565b600082601f830112613636578081fd5b81356136446134bd82614cdb565b81815291506020808301908481018184028601820187101561366557600080fd5b60005b8481101561146857813584529282019290820190600101613668565b600082601f830112613694578081fd5b81516136a26134bd82614cdb565b8181529150602080830190848101818402860182018710156136c357600080fd5b60005b84811015611468578151845292820192908201906001016136c6565b80516001600160e01b0319811681146106aa57600080fd5b600082601f83011261370a578081fd5b81356137186134bd82614cfb565b915080825283602082850101111561372f57600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112613758578081fd5b81516137666134bd82614cfb565b915080825283602082850101111561377d57600080fd5b61146d816020840160208601614d1f565b8051600581106106aa57600080fd5b60006101c08083850312156137b0578182fd5b6137b981614cb4565b9150506137c68383613489565b81526137d58360208401613489565b60208201526137e78360408401613489565b60408201526137f98360608401613489565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff8082111561385b57600080fd5b613867868387016136fa565b8385015261016092508285013591508082111561388357600080fd5b61388f868387016136fa565b838501526101809250828501359150808211156138ab57600080fd5b6138b7868387016136fa565b838501526101a09250828501359150808211156138d357600080fd5b506138e0858286016136fa565b82840152505092915050565b60006101c08083850312156138ff578182fd5b61390881614cb4565b9150506139158383613494565b81526139248360208401613494565b60208201526139368360408401613494565b60408201526139488360608401613494565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156139aa57600080fd5b6139b686838701613748565b838501526101609250828501519150808211156139d257600080fd5b6139de86838701613748565b838501526101809250828501519150808211156139fa57600080fd5b613a0686838701613748565b838501526101a0925082850151915080821115613a2257600080fd5b506138e085828601613748565b600060208284031215613a40578081fd5b813561182781614d59565b60008060408385031215613a5d578081fd5b8235613a6881614d59565b9150602083013567ffffffffffffffff811115613a83578182fd5b613a8f8582860161350b565b9150509250929050565b60008060008060808587031215613aae578182fd5b8435613ab981614d59565b9350602085013567ffffffffffffffff80821115613ad5578384fd5b613ae188838901613626565b94506040870135915080821115613af6578384fd5b613b0288838901613626565b93506060870135915080821115613b17578283fd5b50613b24878288016136fa565b91505092959194509250565b60008060408385031215613b42578182fd5b8235613b4d81614d59565b9150602083013567ffffffffffffffff811115613b68578182fd5b613a8f858286016136fa565b600080600060608486031215613b88578081fd5b8335613b9381614d59565b9250602084013567ffffffffffffffff811115613bae578182fd5b613bba868287016136fa565b925050604084013590509250925092565b60008060408385031215613bdd578182fd5b8235613be881614d59565b946020939093013593505050565b600060208284031215613c07578081fd5b813567ffffffffffffffff811115613c1d578182fd5b6109118482850161349f565b60006020808385031215613c3b578182fd5b825167ffffffffffffffff811115613c51578283fd5b80840185601f820112613c62578384fd5b80519150613c726134bd83614cdb565b8281528381019082850185850284018601891015613c8e578687fd5b8693505b84841015613cb857613ca4898261378e565b835260019390930192918501918501613c92565b50979650505050505050565b600080600060608486031215613cd8578081fd5b833567ffffffffffffffff80821115613cef578283fd5b613cfb878388016135cb565b94506020860135915080821115613d10578283fd5b613d1c8783880161349f565b93506040860135915080821115613d31578283fd5b50613d3e86828701613626565b9150509250925092565b60008060408385031215613d5a578182fd5b823567ffffffffffffffff80821115613d71578384fd5b613d7d868387016135cb565b93506020850135915080821115613d92578283fd5b50613a8f8582860161350b565b60008060408385031215613db1578182fd5b823567ffffffffffffffff80821115613dc8578384fd5b613d7d86838701613626565b600060208284031215613de5578081fd5b81518015158114611827578182fd5b600060208284031215613e05578081fd5b61182783836136e2565b60008060408385031215613e21578182fd5b613e2b84846136e2565b91506020830151613e3b81614d59565b809150509250929050565b60008060008060808587031215613e5b578182fd5b8451613e6681614d6e565b6020860151909450613e7781614d59565b6040860151909350613e8881614d59565b606086015190925067ffffffffffffffff811115613ea4578182fd5b613b2487828801613748565b600080600080600060a08688031215613ec7578283fd5b613ed187876136e2565b94506020860151613ee181614d59565b604087015190945067ffffffffffffffff80821115613efe578485fd5b613f0a89838a01613684565b94506060880151915080821115613f1f578283fd5b613f2b89838a01613684565b93506080880151915080821115613f40578283fd5b50613f4d88828901613748565b9150509295509295909350565b60008060008060808587031215613f6f578182fd5b613f7986866136e2565b93506020850151613f8981614d59565b604086015190935067ffffffffffffffff811115613fa5578283fd5b613fb187828801613748565b606096909601519497939650505050565b600080600060608486031215613fd6578081fd5b613fe085856136e2565b92506020840151613ff081614d59565b80925050604084015190509250925092565b600080600060608486031215614016578081fd5b835161402181614d6e565b602085015190935067ffffffffffffffff8082111561403e578283fd5b61404a87838801613684565b9350604086015191508082111561405f578283fd5b50613d3e86828701613570565b60006020828403121561407d578081fd5b813567ffffffffffffffff811115614093578182fd5b610911848285016136fa565b6000602082840312156140b0578081fd5b815167ffffffffffffffff8111156140c6578182fd5b61091184828501613748565b6000602082840312156140e3578081fd5b815161182781614d59565b6000602082840312156140ff578081fd5b815160058110611827578182fd5b60008060008060808587031215614122578182fd5b845167ffffffffffffffff80821115614139578384fd5b61414588838901613748565b955060209150818701518181111561415b578485fd5b80880189601f82011261416c578586fd5b8051915061417c6134bd83614cdb565b82815284810190828601885b858110156141b15761419f8e8984518801016138ec565b84529287019290870190600101614188565b505060408b01519098509450505050808211156141cc578384fd5b6141d888838901613684565b935060608701519150808211156141ed578283fd5b50613b2487828801613570565b60006060828403121561420b578081fd5b6142156060614cb4565b825160078110614223578283fd5b8152602083810151908201526040928301519281019290925250919050565b600080600060608486031215614256578081fd5b833567ffffffffffffffff81111561426c578182fd5b6142788682870161379d565b935050602084013561428981614d59565b929592945050506040919091013590565b600080604083850312156142ac578182fd5b823567ffffffffffffffff808211156142c3578384fd5b6142cf8683870161379d565b935060208501359150808211156142e4578283fd5b50613a8f858286016136fa565b600080600060608486031215614305578081fd5b833567ffffffffffffffff81111561431b578182fd5b6143278682870161379d565b93505060208401359150604084013561433f81614d59565b809150509250925092565b60008060006060848603121561435e578081fd5b833567ffffffffffffffff80821115614375578283fd5b81860160a08189031215614387578384fd5b61439160a0614cb4565b92508035835260208101356020840152604081013560408401526143b88860608301613489565b60608401526080810135828111156143ce578485fd5b6143da898284016136fa565b6080850152509194505050602084013591506143f98560408601613489565b90509250925092565b600060208284031215614413578081fd5b5051919050565b6001600160a01b03169052565b6000815180845260208401935060208301825b828110156144615781516001600160a01b031686526020958601959091019060010161443a565b5093949350505050565b600081518084526020840180819550602083028101915060208501845b848110156144b65782840388526144a08483516144f3565b6020988901989094509190910190600101614488565b50919695505050505050565b6000815180845260208401935060208301825b828110156144615781518652602095860195909101906001016144d5565b6000815180845261450b816020860160208601614d1f565b601f01601f19169290920160200192915050565b80516007811061452b57fe5b825260208181015190830152604090810151910152565b60006101c061455284845161441a565b6020830151614564602086018261441a565b506040830151614577604086018261441a565b50606083015161458a606086018261441a565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e08501526101008084015181860152506101208084015181860152506101408084015182828701526145e3838701826144f3565b9150506101609150818401518582038387015261460082826144f3565b92505050610180808401518583038287015261461c83826144f3565b9150506101a09150818401518582038387015261463982826144f3565b9695505050505050565b60008251614655818460208701614d1f565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6000608082016001600160a01b03871683526080602084015280865180835260a08501915060a060208202860101925060208801845b82811015614712577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608786030184526146fd858351614542565b945060209384019391909101906001016146c3565b5050505082810360408401526147288186614427565b838103606085015261473a81866144c2565b98975050505050505050565b60006001600160a01b03861682526080602083015261476860808301866144c2565b828103604084015261477a81866144c2565b838103606085015261473a81866144f3565b60006001600160a01b0385168252606060208301526147ae60608301856144f3565b9050826040830152949350505050565b60006001600160a01b038087168352608060208401526147e16080840187614542565b94166040830152506060015292915050565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000918401906040840190835b8181101561484d57835161483981614d4f565b835260209384019390920191600101614826565b509095945050505050565b606080825284519082018190526000906020906080840190828801845b8281101561489b5761488884835161451f565b6060939093019290840190600101614875565b505050838103828501526148af81876144c2565b84810360408601528551808252908301915082860190845b818110156148e55782511515845292840192918401916001016148c7565b509198975050505050505050565b60006020825261182760208301846144c2565b60006040825261491960408301856144c2565b602083820381850152818551808452828401915082838202850101838801865b8381101561496757601f198784030185526149558383516144f3565b94860194925090850190600101614939565b50909998505050505050505050565b60006040825261498960408301856144c2565b82810360208401526118db81856144c2565b90815260200190565b6001600160e01b031991909116815260200190565b6001600160e01b03199290921682526001600160a01b0316602082015260400190565b60006001600160e01b0319861682526001600160a01b0380861660208401528085166040840152506080606083015261463960808301846144f3565b60006001600160e01b0319871682526001600160a01b038616602083015260a06040830152614a4a60a08301866144c2565b8281036060840152614a5c81866144c2565b8381036080850152614a6e81866144f3565b9998505050505050505050565b60006001600160e01b0319861682526001600160a01b038516602083015260806040830152614aad60808301856144f3565b905082606083015295945050505050565b6001600160e01b03199390931683526001600160a01b03919091166020830152604082015260600190565b60006001600160e01b03198516825260606020830152614b0c60608301856144c2565b8281036040840152614639818561446b565b60006020825261182760208301846144f3565b600060808252614b4460808301876144f3565b6001600160a01b03958616602084015293909416604082015260ff9190911660609091015292915050565b6060810160048510614b7d57fe5b938152602081019290925260409091015290565b6060810160088510614b7d57fe5b60208101614bac83614d4f565b91905290565b600060808252614bc560808301876144f3565b602083820381850152818751808452828401915082838202850101838a01865b83811015614c1357601f19878403018552614c01838351614542565b94860194925090850190600101614be5565b50508681036040880152614c27818a6144c2565b9450505050508281036060840152614c3f818561446b565b979650505050505050565b60a08101614c58828661451f565b8360608301528215156080830152949350505050565b6000602082526118276020830184614542565b600060408252614c946040830185614542565b82810360208401526118db81856144f3565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715614cd357600080fd5b604052919050565b600067ffffffffffffffff821115614cf1578081fd5b5060209081020190565b600067ffffffffffffffff821115614d11578081fd5b50601f01601f191660200190565b60005b83811015614d3a578181015183820152602001614d22565b83811115614d49576000848401525b50505050565b6005811061073157fe5b6001600160a01b038116811461073157600080fd5b6001600160e01b03198116811461073157600080fdfea365627a7a7231582034aeeb2766e909a7bf6404cf5556e26fa49952bdd5ea533d25447be58f55ed9a6c6578706572696d656e74616cf564736f6c63430005100040'; public static contractName = 'DevUtils'; private readonly _methodABIIndex: { [name: string]: number } = {}; public static async deployFrom0xArtifactAsync( @@ -48,8 +50,8 @@ export class DevUtilsContract extends BaseContract { supportedProvider: SupportedProvider, txDefaults: Partial, logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, - _exchange: string, - _chaiBridge: string, + exchange_: string, + chaiBridge_: string, ): Promise { assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ schemas.addressSchema, @@ -74,18 +76,65 @@ export class DevUtilsContract extends BaseContract { provider, txDefaults, logDecodeDependenciesAbiOnly, - _exchange, - _chaiBridge, + exchange_, + chaiBridge_, ); } + + public static async deployWithLibrariesFrom0xArtifactAsync( + artifact: ContractArtifact, + libraryArtifacts: { [libraryName: string]: ContractArtifact }, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + exchange_: string, + chaiBridge_: string, + ): 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 DevUtilsContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return DevUtilsContract.deployAsync( + bytecode, + abi, + provider, + txDefaults, + logDecodeDependenciesAbiOnly, + exchange_, + chaiBridge_, + ); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, supportedProvider: SupportedProvider, txDefaults: Partial, logDecodeDependencies: { [contractName: string]: ContractAbi }, - _exchange: string, - _chaiBridge: string, + exchange_: string, + chaiBridge_: string, ): Promise { assert.isHexString('bytecode', bytecode); assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [ @@ -95,14 +144,14 @@ export class DevUtilsContract extends BaseContract { ]); const provider = providerUtils.standardizeOrThrow(supportedProvider); const constructorAbi = BaseContract._lookupConstructorAbi(abi); - [_exchange, _chaiBridge] = BaseContract._formatABIDataItemList( + [exchange_, chaiBridge_] = BaseContract._formatABIDataItemList( constructorAbi.inputs, - [_exchange, _chaiBridge], + [exchange_, chaiBridge_], BaseContract._bigNumberToString, ); const iface = new ethers.utils.Interface(abi); const deployInfo = iface.deployFunction; - const txData = deployInfo.encode(bytecode, [_exchange, _chaiBridge]); + const txData = deployInfo.encode(bytecode, [exchange_, chaiBridge_]); const web3Wrapper = new Web3Wrapper(provider); const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync( { @@ -121,7 +170,7 @@ export class DevUtilsContract extends BaseContract { txDefaults, logDecodeDependencies, ); - contractInstance.constructorArgs = [_exchange, _chaiBridge]; + contractInstance.constructorArgs = [exchange_, chaiBridge_]; return contractInstance; } @@ -133,11 +182,11 @@ export class DevUtilsContract extends BaseContract { { inputs: [ { - name: '_exchange', + name: 'exchange_', type: 'address', }, { - name: '_chaiBridge', + name: 'chaiBridge_', type: 'address', }, ], @@ -162,52 +211,16 @@ export class DevUtilsContract extends BaseContract { }, { constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeAssetProxyDispatchError', - outputs: [ - { - name: 'errorCode', - type: 'uint8', - }, - { - name: 'orderHash', - type: 'bytes32', - }, - { - name: 'assetData', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeAssetProxyExistsError', + inputs: [], + name: 'chaiBridgeAddress', outputs: [ { - name: 'assetProxyId', - type: 'bytes4', - }, - { - name: 'assetProxyAddress', + name: '', type: 'address', }, ], payable: false, - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, { @@ -229,64 +242,6 @@ export class DevUtilsContract extends BaseContract { stateMutability: 'pure', type: 'function', }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeAssetProxyTransferError', - outputs: [ - { - name: 'orderHash', - type: 'bytes32', - }, - { - name: 'assetData', - type: 'bytes', - }, - { - name: 'errorData', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeEIP1271SignatureError', - outputs: [ - { - name: 'verifyingContractAddress', - type: 'address', - }, - { - name: 'data', - type: 'bytes', - }, - { - name: 'signature', - type: 'bytes', - }, - { - name: 'errorData', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, { constant: true, inputs: [ @@ -403,83 +358,6 @@ export class DevUtilsContract extends BaseContract { stateMutability: 'pure', type: 'function', }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeExchangeInvalidContextError', - outputs: [ - { - name: 'errorCode', - type: 'uint8', - }, - { - name: 'orderHash', - type: 'bytes32', - }, - { - name: 'contextAddress', - type: 'address', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeFillError', - outputs: [ - { - name: 'errorCode', - type: 'uint8', - }, - { - name: 'orderHash', - type: 'bytes32', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeIncompleteFillError', - outputs: [ - { - name: 'errorCode', - type: 'uint8', - }, - { - name: 'expectedAssetFillAmount', - type: 'uint256', - }, - { - name: 'actualAssetFillAmount', - type: 'uint256', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, { constant: true, inputs: [ @@ -507,164 +385,6 @@ export class DevUtilsContract extends BaseContract { stateMutability: 'pure', type: 'function', }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeNegativeSpreadError', - outputs: [ - { - name: 'leftOrderHash', - type: 'bytes32', - }, - { - name: 'rightOrderHash', - type: 'bytes32', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeOrderEpochError', - outputs: [ - { - name: 'makerAddress', - type: 'address', - }, - { - name: 'orderSenderAddress', - type: 'address', - }, - { - name: 'currentEpoch', - type: 'uint256', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeOrderStatusError', - outputs: [ - { - name: 'orderHash', - type: 'bytes32', - }, - { - name: 'orderStatus', - type: 'uint8', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeSignatureError', - outputs: [ - { - name: 'errorCode', - type: 'uint8', - }, - { - name: 'hash', - type: 'bytes32', - }, - { - name: 'signerAddress', - type: 'address', - }, - { - name: 'signature', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeSignatureValidatorNotApprovedError', - outputs: [ - { - name: 'signerAddress', - type: 'address', - }, - { - name: 'validatorAddress', - type: 'address', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', - }, - ], - name: 'decodeSignatureWalletError', - outputs: [ - { - name: 'hash', - type: 'bytes32', - }, - { - name: 'signerAddress', - type: 'address', - }, - { - name: 'signature', - type: 'bytes', - }, - { - name: 'errorData', - type: 'bytes', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, { constant: true, inputs: [ @@ -700,42 +420,85 @@ export class DevUtilsContract extends BaseContract { constant: true, inputs: [ { - name: 'encoded', + name: 'transactionData', type: 'bytes', }, ], - name: 'decodeTransactionError', + name: 'decodeZeroExTransactionData', outputs: [ { - name: 'errorCode', - type: 'uint8', + name: 'functionName', + type: 'string', }, { - name: 'transactionHash', - type: 'bytes32', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - { - constant: true, - inputs: [ - { - name: 'encoded', - type: 'bytes', + 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: 'decodeTransactionExecutionError', - outputs: [ { - name: 'transactionHash', - type: 'bytes32', + name: 'takerAssetFillAmounts', + type: 'uint256[]', }, { - name: 'errorData', - type: 'bytes', + name: 'signatures', + type: 'bytes[]', }, ], payable: false, @@ -854,15 +617,71 @@ export class DevUtilsContract extends BaseContract { type: 'bytes32', }, ], - name: 'encodeStaticCallAssetData', + name: 'encodeStaticCallAssetData', + outputs: [ + { + name: 'assetData', + type: 'bytes', + }, + ], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'erc1155ProxyAddress', + outputs: [ + { + name: '', + type: 'address', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'erc20ProxyAddress', + outputs: [ + { + name: '', + type: 'address', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'erc721ProxyAddress', + outputs: [ + { + name: '', + type: 'address', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, + { + constant: true, + inputs: [], + name: 'exchangeAddress', outputs: [ { - name: 'assetData', - type: 'bytes', + name: '', + type: 'address', }, ], payable: false, - stateMutability: 'pure', + stateMutability: 'view', type: 'function', }, { @@ -1662,16 +1481,82 @@ export class DevUtilsContract extends BaseContract { stateMutability: 'pure', type: 'function', }, + { + constant: true, + inputs: [], + name: 'staticCallProxyAddress', + outputs: [ + { + name: '', + type: 'address', + }, + ], + 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 DevUtilsContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = DevUtilsContract.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 DevUtilsContract; @@ -1679,6 +1564,7 @@ export class DevUtilsContract extends BaseContract { 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 DevUtilsContract; @@ -1686,6 +1572,7 @@ export class DevUtilsContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as DevUtilsContract; @@ -1696,351 +1583,108 @@ export class DevUtilsContract extends BaseContract { public EIP712_EXCHANGE_DOMAIN_HASH(): ContractFunctionObj { const self = (this as any) as DevUtilsContract; const functionSignature = 'EIP712_EXCHANGE_DOMAIN_HASH()'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._performCallAsync( - { ...callData, data: this.getABIEncodedTransactionData() }, - defaultBlock, - ); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, []); - }, - }; - } - /** - * Decompose an ABI-encoded AssetProxyDispatchError. - * @param encoded ABI-encoded revert error. - * @returns errorCode The error code.orderHash Hash of the order being dispatched.assetData Asset data of the order being dispatched. - */ - public decodeAssetProxyDispatchError(encoded: string): ContractFunctionObj<[number, string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeAssetProxyDispatchError(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[number, string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decompose an ABI-encoded AssetProxyExistsError. - * @param encoded ABI-encoded revert error. - * @returns assetProxyId Id of asset proxy.assetProxyAddress The address of the asset proxy. - */ - public decodeAssetProxyExistsError(encoded: string): ContractFunctionObj<[string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeAssetProxyExistsError(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decode AssetProxy identifier - * @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC- - * 721, ERC1155, or MultiAsset asset. - * @returns The AssetProxy identifier - */ - public decodeAssetProxyId(assetData: string): ContractFunctionObj { - const self = (this as any) as DevUtilsContract; - assert.isString('assetData', assetData); - const functionSignature = 'decodeAssetProxyId(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [assetData]); - }, - }; - } - /** - * Decompose an ABI-encoded AssetProxyTransferError. - * @param encoded ABI-encoded revert error. - * @returns orderHash Hash of the order being dispatched.assetData Asset data of the order being dispatched.errorData ABI-encoded revert data from the asset proxy. - */ - public decodeAssetProxyTransferError(encoded: string): ContractFunctionObj<[string, string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeAssetProxyTransferError(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[string, string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decompose an ABI-encoded SignatureValidatorError. - * @param encoded ABI-encoded revert error. - * @returns signerAddress The expected signer of the hash.signature The full signature bytes.errorData The revert data thrown by the validator contract. - */ - public decodeEIP1271SignatureError(encoded: string): ContractFunctionObj<[string, string, string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeEIP1271SignatureError(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[string, string, string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decode ERC-1155 asset data from the format described in the AssetProxy contract specification. - * @param assetData AssetProxy-compliant asset data describing an ERC-1155 set - * of assets. - * @returns The ERC-1155 AssetProxy identifier, the address of the ERC-1155 contract hosting the assets, an array of the identifiers of the assets to be traded, an array of asset amounts to be traded, and callback data. Each element of the arrays corresponds to the same-indexed element of the other array. Return values specified as `memory` are returned as pointers to locations within the memory of the input parameter `assetData`. - */ - public decodeERC1155AssetData( - assetData: string, - ): ContractFunctionObj<[string, string, BigNumber[], BigNumber[], string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('assetData', assetData); - const functionSignature = 'decodeERC1155AssetData(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[string, string, BigNumber[], BigNumber[], string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber[], BigNumber[], string]>( - rawCallResult, - ); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [assetData]); - }, - }; - } - /** - * Decode ERC-20 asset data from the format described in the AssetProxy contract specification. - * @param assetData AssetProxy-compliant asset data describing an ERC-20 asset. - * @returns The AssetProxy identifier, and the address of the ERC-20 contract hosting this asset. - */ - public decodeERC20AssetData(assetData: string): ContractFunctionObj<[string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('assetData', assetData); - const functionSignature = 'decodeERC20AssetData(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [assetData]); - }, - }; - } - /** - * Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification. - * @param assetData AssetProxy-compliant asset data describing an ERC20Bridge - * asset - * @returns The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address of the bridge contract, and extra data to be passed to the bridge contract. - */ - public decodeERC20BridgeAssetData(assetData: string): ContractFunctionObj<[string, string, string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('assetData', assetData); - const functionSignature = 'decodeERC20BridgeAssetData(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[string, string, string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [assetData]); - }, - }; - } - /** - * Decode ERC-721 asset data from the format described in the AssetProxy contract specification. - * @param assetData AssetProxy-compliant asset data describing an ERC-721 - * asset. - * @returns The ERC-721 AssetProxy identifier, the address of the ERC-721 contract hosting this asset, and the identifier of the specific asset to be traded. - */ - public decodeERC721AssetData(assetData: string): ContractFunctionObj<[string, string, BigNumber]> { - const self = (this as any) as DevUtilsContract; - assert.isString('assetData', assetData); - const functionSignature = 'decodeERC721AssetData(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[string, string, BigNumber]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [assetData]); - }, - }; - } - /** - * Decompose an ABI-encoded OrderStatusError. - * @param encoded ABI-encoded revert error. - * @returns errorCode Error code that corresponds to invalid maker, taker, or sender.orderHash The order hash.contextAddress The maker, taker, or sender address - */ - public decodeExchangeInvalidContextError(encoded: string): ContractFunctionObj<[number, string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeExchangeInvalidContextError(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[number, string, string]> { + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, string, string]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, []); }, }; } - /** - * Decompose an ABI-encoded FillError. - * @param encoded ABI-encoded revert error. - * @returns errorCode The error code.orderHash The order hash. - */ - public decodeFillError(encoded: string): ContractFunctionObj<[number, string]> { + public chaiBridgeAddress(): ContractFunctionObj { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeFillError(bytes)'; + const functionSignature = 'chaiBridgeAddress()'; return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[number, string]> { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, string]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, []); }, }; } /** - * Decompose an ABI-encoded IncompleteFillError. - * @param encoded ABI-encoded revert error. - * @returns orderHash Hash of the order being filled. + * Decode AssetProxy identifier + * @param assetData AssetProxy-compliant asset data describing an ERC-20, ERC- + * 721, ERC1155, or MultiAsset asset. + * @returns The AssetProxy identifier */ - public decodeIncompleteFillError(encoded: string): ContractFunctionObj<[number, BigNumber, BigNumber]> { + public decodeAssetProxyId(assetData: string): ContractFunctionObj { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeIncompleteFillError(bytes)'; + assert.isString('assetData', assetData); + const functionSignature = 'decodeAssetProxyId(bytes)'; return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise<[number, BigNumber, BigNumber]> { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, BigNumber, BigNumber]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [assetData]); }, }; } /** - * Decode multi-asset data from the format described in the AssetProxy contract specification. - * @param assetData AssetProxy-compliant data describing a multi-asset basket. - * @returns The Multi-Asset AssetProxy identifier, an array of the amounts of the assets to be traded, and an array of the AssetProxy-compliant data describing each asset to be traded. Each element of the arrays corresponds to the same-indexed element of the other array. + * Decode ERC-1155 asset data from the format described in the AssetProxy contract specification. + * @param assetData AssetProxy-compliant asset data describing an ERC-1155 set + * of assets. + * @returns The ERC-1155 AssetProxy identifier, the address of the ERC-1155 contract hosting the assets, an array of the identifiers of the assets to be traded, an array of asset amounts to be traded, and callback data. Each element of the arrays corresponds to the same-indexed element of the other array. Return values specified as `memory` are returned as pointers to locations within the memory of the input parameter `assetData`. */ - public decodeMultiAssetData(assetData: string): ContractFunctionObj<[string, BigNumber[], string[]]> { + public decodeERC1155AssetData( + assetData: string, + ): ContractFunctionObj<[string, string, BigNumber[], BigNumber[], string]> { const self = (this as any) as DevUtilsContract; assert.isString('assetData', assetData); - const functionSignature = 'decodeMultiAssetData(bytes)'; + const functionSignature = 'decodeERC1155AssetData(bytes)'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise<[string, BigNumber[], string[]]> { + ): Promise<[string, string, BigNumber[], BigNumber[], string]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, BigNumber[], string[]]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber[], BigNumber[], string]>( + rawCallResult, + ); }, getABIEncodedTransactionData(): string { return self._strictEncodeArguments(functionSignature, [assetData]); @@ -2048,149 +1692,137 @@ export class DevUtilsContract extends BaseContract { }; } /** - * Decompose an ABI-encoded NegativeSpreadError. - * @param encoded ABI-encoded revert error. - * @returns leftOrderHash Hash of the left order being matched.rightOrderHash Hash of the right order being matched. + * Decode ERC-20 asset data from the format described in the AssetProxy contract specification. + * @param assetData AssetProxy-compliant asset data describing an ERC-20 asset. + * @returns The AssetProxy identifier, and the address of the ERC-20 contract hosting this asset. */ - public decodeNegativeSpreadError(encoded: string): ContractFunctionObj<[string, string]> { + public decodeERC20AssetData(assetData: string): ContractFunctionObj<[string, string]> { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeNegativeSpreadError(bytes)'; + assert.isString('assetData', assetData); + const functionSignature = 'decodeERC20AssetData(bytes)'; return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, string]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [assetData]); }, }; } /** - * Decompose an ABI-encoded OrderEpochError. - * @param encoded ABI-encoded revert error. - * @returns makerAddress The order maker.orderSenderAddress The order sender.currentEpoch The current epoch for the maker. + * Decode ERC20Bridge asset data from the format described in the AssetProxy contract specification. + * @param assetData AssetProxy-compliant asset data describing an ERC20Bridge + * asset + * @returns The ERC20BridgeProxy identifier, the address of the ERC20 token to transfer, the address of the bridge contract, and extra data to be passed to the bridge contract. */ - public decodeOrderEpochError(encoded: string): ContractFunctionObj<[string, string, BigNumber]> { + public decodeERC20BridgeAssetData(assetData: string): ContractFunctionObj<[string, string, string, string]> { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeOrderEpochError(bytes)'; + assert.isString('assetData', assetData); + const functionSignature = 'decodeERC20BridgeAssetData(bytes)'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise<[string, string, BigNumber]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decompose an ABI-encoded OrderStatusError. - * @param encoded ABI-encoded revert error. - * @returns orderHash The order hash.orderStatus The order status. - */ - public decodeOrderStatusError(encoded: string): ContractFunctionObj<[string, number]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeOrderStatusError(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, number]> { + ): Promise<[string, string, string, string]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, number]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [assetData]); }, }; } /** - * Decompose an ABI-encoded SignatureError. - * @param encoded ABI-encoded revert error. - * @returns errorCode The error code.signerAddress The expected signer of the hash.signature The full signature. + * Decode ERC-721 asset data from the format described in the AssetProxy contract specification. + * @param assetData AssetProxy-compliant asset data describing an ERC-721 + * asset. + * @returns The ERC-721 AssetProxy identifier, the address of the ERC-721 contract hosting this asset, and the identifier of the specific asset to be traded. */ - public decodeSignatureError(encoded: string): ContractFunctionObj<[number, string, string, string]> { + public decodeERC721AssetData(assetData: string): ContractFunctionObj<[string, string, BigNumber]> { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeSignatureError(bytes)'; + assert.isString('assetData', assetData); + const functionSignature = 'decodeERC721AssetData(bytes)'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise<[number, string, string, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, string, string, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decompose an ABI-encoded SignatureValidatorNotApprovedError. - * @param encoded ABI-encoded revert error. - * @returns signerAddress The expected signer of the hash.validatorAddress The expected validator. - */ - public decodeSignatureValidatorNotApprovedError(encoded: string): ContractFunctionObj<[string, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeSignatureValidatorNotApprovedError(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, string]> { + ): Promise<[string, string, BigNumber]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue<[string, string, BigNumber]>(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [assetData]); }, }; } /** - * Decompose an ABI-encoded SignatureWalletError. - * @param encoded ABI-encoded revert error. - * @returns errorCode The error code.signerAddress The expected signer of the hash.signature The full signature bytes.errorData The revert data thrown by the validator contract. + * Decode multi-asset data from the format described in the AssetProxy contract specification. + * @param assetData AssetProxy-compliant data describing a multi-asset basket. + * @returns The Multi-Asset AssetProxy identifier, an array of the amounts of the assets to be traded, and an array of the AssetProxy-compliant data describing each asset to be traded. Each element of the arrays corresponds to the same-indexed element of the other array. */ - public decodeSignatureWalletError(encoded: string): ContractFunctionObj<[string, string, string, string]> { + public decodeMultiAssetData(assetData: string): ContractFunctionObj<[string, BigNumber[], string[]]> { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeSignatureWalletError(bytes)'; + assert.isString('assetData', assetData); + const functionSignature = 'decodeMultiAssetData(bytes)'; return { async callAsync( callData: Partial = {}, defaultBlock?: BlockParam, - ): Promise<[string, string, string, string]> { + ): Promise<[string, BigNumber[], string[]]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue<[string, BigNumber[], string[]]>(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [assetData]); }, }; } @@ -2211,7 +1843,15 @@ export class DevUtilsContract extends BaseContract { defaultBlock?: BlockParam, ): Promise<[string, string, string, string]> { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue<[string, string, string, string]>(rawCallResult); @@ -2222,48 +1862,105 @@ export class DevUtilsContract extends BaseContract { }; } /** - * Decompose an ABI-encoded TransactionError. - * @param encoded ABI-encoded revert error. - * @returns errorCode The error code.transactionHash Hash of the transaction. - */ - public decodeTransactionError(encoded: string): ContractFunctionObj<[number, string]> { - const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeTransactionError(bytes)'; - - return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[number, string]> { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[number, string]>(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); - }, - }; - } - /** - * Decompose an ABI-encoded TransactionExecutionError. - * @param encoded ABI-encoded revert error. - * @returns transactionHash Hash of the transaction.errorData Error thrown by exeucteTransaction(). + * Decodes the call data for an Exchange contract method call. + * @param transactionData ABI-encoded calldata for an Exchange contract + * method call. + * @returns The name of the function called, and the parameters it was given. For single-order fills and cancels, the arrays will have just one element. */ - public decodeTransactionExecutionError(encoded: string): ContractFunctionObj<[string, string]> { + public decodeZeroExTransactionData( + transactionData: string, + ): ContractFunctionObj< + [ + string, + 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; + }>, + BigNumber[], + string[] + ] + > { const self = (this as any) as DevUtilsContract; - assert.isString('encoded', encoded); - const functionSignature = 'decodeTransactionExecutionError(bytes)'; + assert.isString('transactionData', transactionData); + const functionSignature = 'decodeZeroExTransactionData(bytes)'; return { - async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise<[string, string]> { + async callAsync( + callData: Partial = {}, + defaultBlock?: BlockParam, + ): Promise< + [ + string, + 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; + }>, + BigNumber[], + string[] + ] + > { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue<[string, string]>(rawCallResult); + return abiEncoder.strictDecodeReturnValue< + [ + string, + 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; + }>, + BigNumber[], + string[] + ] + >(rawCallResult); }, getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [encoded]); + return self._strictEncodeArguments(functionSignature, [transactionData]); }, }; } @@ -2293,7 +1990,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -2322,7 +2027,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -2348,7 +2061,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -2374,7 +2095,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -2407,7 +2136,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -2421,6 +2158,86 @@ export class DevUtilsContract extends BaseContract { }, }; } + public erc1155ProxyAddress(): ContractFunctionObj { + const self = (this as any) as DevUtilsContract; + const functionSignature = 'erc1155ProxyAddress()'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, []); + }, + }; + } + public erc20ProxyAddress(): ContractFunctionObj { + const self = (this as any) as DevUtilsContract; + const functionSignature = 'erc20ProxyAddress()'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, []); + }, + }; + } + public erc721ProxyAddress(): ContractFunctionObj { + const self = (this as any) as DevUtilsContract; + const functionSignature = 'erc721ProxyAddress()'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, []); + }, + }; + } + public exchangeAddress(): ContractFunctionObj { + const self = (this as any) as DevUtilsContract; + const functionSignature = 'exchangeAddress()'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, []); + }, + }; + } /** * Returns the number of asset(s) (described by assetData) that the corresponding AssetProxy contract is authorized to spend. When the asset data contains multiple assets (eg for Multi-Asset), the return value indicates how many complete "baskets" of those assets may be spent by all of the corresponding AssetProxy contracts. * @param ownerAddress Owner of the assets specified by assetData. @@ -2819,7 +2636,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -3273,7 +3098,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -3284,7 +3117,7 @@ export class DevUtilsContract extends BaseContract { }; } /** - * Gets the amount of an asset transferable by the owner. + * Gets the amount of an asset transferable by the maker of an order. * @param ownerAddress Address of the owner of the asset. * @param assetData Description of tokens, per the AssetProxy contract * specification. @@ -3350,7 +3183,15 @@ export class DevUtilsContract extends BaseContract { return { async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + let rawCallResult; + if (self._deployedBytecodeIfExists) { + rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + } else { + rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + } const abiEncoder = self._lookupAbiEncoder(functionSignature); BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue(rawCallResult); @@ -3360,6 +3201,26 @@ export class DevUtilsContract extends BaseContract { }, }; } + public staticCallProxyAddress(): ContractFunctionObj { + const self = (this as any) as DevUtilsContract; + const functionSignature = 'staticCallProxyAddress()'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, []); + }, + }; + } constructor( address: string, diff --git a/packages/contract-wrappers/src/generated-wrappers/erc20_token.ts b/packages/contract-wrappers/src/generated-wrappers/erc20_token.ts index 419c4c21ef..50e50adf4a 100644 --- a/packages/contract-wrappers/src/generated-wrappers/erc20_token.ts +++ b/packages/contract-wrappers/src/generated-wrappers/erc20_token.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -54,6 +55,7 @@ export interface ERC20TokenTransferEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC20TokenContract extends BaseContract { @@ -89,6 +91,43 @@ export class ERC20TokenContract extends BaseContract { } return ERC20TokenContract.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 ERC20TokenContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return ERC20TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -314,12 +353,64 @@ export class ERC20TokenContract extends BaseContract { 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 ERC20TokenContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = ERC20TokenContract.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 ERC20TokenContract; @@ -327,6 +418,7 @@ export class ERC20TokenContract extends BaseContract { 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 ERC20TokenContract; @@ -334,6 +426,7 @@ export class ERC20TokenContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as ERC20TokenContract; @@ -608,6 +701,7 @@ export class ERC20TokenContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -615,12 +709,14 @@ export class ERC20TokenContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The ERC20Token contract event you would like to subscribe to. @@ -646,6 +742,7 @@ export class ERC20TokenContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/erc721_token.ts b/packages/contract-wrappers/src/generated-wrappers/erc721_token.ts index 1a7996d3c3..5b78a4173a 100644 --- a/packages/contract-wrappers/src/generated-wrappers/erc721_token.ts +++ b/packages/contract-wrappers/src/generated-wrappers/erc721_token.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -64,6 +65,7 @@ export interface ERC721TokenTransferEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ERC721TokenContract extends BaseContract { @@ -99,6 +101,43 @@ export class ERC721TokenContract extends BaseContract { } return ERC721TokenContract.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 ERC721TokenContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return ERC721TokenContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -404,12 +443,64 @@ export class ERC721TokenContract extends BaseContract { 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 ERC721TokenContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = ERC721TokenContract.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 ERC721TokenContract; @@ -417,6 +508,7 @@ export class ERC721TokenContract extends BaseContract { 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 ERC721TokenContract; @@ -424,6 +516,7 @@ export class ERC721TokenContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as ERC721TokenContract; @@ -868,6 +961,7 @@ export class ERC721TokenContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -875,12 +969,14 @@ export class ERC721TokenContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The ERC721Token contract event you would like to subscribe to. @@ -906,6 +1002,7 @@ export class ERC721TokenContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/exchange.ts b/packages/contract-wrappers/src/generated-wrappers/exchange.ts index f044bb0e09..9e2c9902ee 100644 --- a/packages/contract-wrappers/src/generated-wrappers/exchange.ts +++ b/packages/contract-wrappers/src/generated-wrappers/exchange.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -120,6 +121,7 @@ export interface ExchangeTransactionExecutionEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ExchangeContract extends BaseContract { @@ -156,6 +158,44 @@ export class ExchangeContract extends BaseContract { } return ExchangeContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, chainId); } + + public static async deployWithLibrariesFrom0xArtifactAsync( + artifact: ContractArtifact, + libraryArtifacts: { [libraryName: string]: ContractArtifact }, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + chainId: BigNumber, + ): 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 ExchangeContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return ExchangeContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly, chainId); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -3113,12 +3153,64 @@ export class ExchangeContract extends BaseContract { 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 ExchangeContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = ExchangeContract.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 ExchangeContract; @@ -3126,6 +3218,7 @@ export class ExchangeContract extends BaseContract { 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 ExchangeContract; @@ -3133,6 +3226,7 @@ export class ExchangeContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as ExchangeContract; @@ -5879,6 +5973,7 @@ export class ExchangeContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -5886,12 +5981,14 @@ export class ExchangeContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The Exchange contract event you would like to subscribe to. @@ -5917,6 +6014,7 @@ export class ExchangeContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/forwarder.ts b/packages/contract-wrappers/src/generated-wrappers/forwarder.ts index 5f12fccbc1..2ad665fec3 100644 --- a/packages/contract-wrappers/src/generated-wrappers/forwarder.ts +++ b/packages/contract-wrappers/src/generated-wrappers/forwarder.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -46,6 +47,7 @@ export interface ForwarderOwnershipTransferredEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class ForwarderContract extends BaseContract { @@ -93,6 +95,55 @@ export class ForwarderContract extends BaseContract { _weth, ); } + + public static async deployWithLibrariesFrom0xArtifactAsync( + artifact: ContractArtifact, + libraryArtifacts: { [libraryName: string]: ContractArtifact }, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + _exchange: string, + _exchangeV2: string, + _weth: string, + ): 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 ForwarderContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return ForwarderContract.deployAsync( + bytecode, + abi, + provider, + txDefaults, + logDecodeDependenciesAbiOnly, + _exchange, + _exchangeV2, + _weth, + ); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -459,12 +510,64 @@ export class ForwarderContract extends BaseContract { 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 ForwarderContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = ForwarderContract.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 ForwarderContract; @@ -472,6 +575,7 @@ export class ForwarderContract extends BaseContract { 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 ForwarderContract; @@ -479,6 +583,7 @@ export class ForwarderContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as ForwarderContract; @@ -903,6 +1008,7 @@ export class ForwarderContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -910,12 +1016,14 @@ export class ForwarderContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The Forwarder contract event you would like to subscribe to. @@ -941,6 +1049,7 @@ export class ForwarderContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/i_asset_data.ts b/packages/contract-wrappers/src/generated-wrappers/i_asset_data.ts index bbe382d072..5419c0e52d 100644 --- a/packages/contract-wrappers/src/generated-wrappers/i_asset_data.ts +++ b/packages/contract-wrappers/src/generated-wrappers/i_asset_data.ts @@ -9,6 +9,7 @@ import { BaseContract, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -25,7 +26,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -33,6 +34,7 @@ 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 IAssetDataContract extends BaseContract { @@ -67,6 +69,43 @@ export class IAssetDataContract extends BaseContract { } return IAssetDataContract.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 IAssetDataContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return IAssetDataContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -237,12 +276,64 @@ export class IAssetDataContract extends BaseContract { 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 IAssetDataContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = IAssetDataContract.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 IAssetDataContract; @@ -250,6 +341,7 @@ export class IAssetDataContract extends BaseContract { 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 IAssetDataContract; @@ -257,6 +349,7 @@ export class IAssetDataContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as IAssetDataContract; 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 index ee08395fbe..b742a4b9c3 100644 --- a/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts +++ b/packages/contract-wrappers/src/generated-wrappers/i_erc20_bridge_sampler.ts @@ -9,6 +9,7 @@ import { BaseContract, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -25,7 +26,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -33,6 +34,7 @@ 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 { @@ -73,6 +75,49 @@ export class IERC20BridgeSamplerContract extends BaseContract { 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.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return IERC20BridgeSamplerContract.deployAsync( + bytecode, + abi, + provider, + txDefaults, + logDecodeDependenciesAbiOnly, + ); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -731,12 +776,64 @@ export class IERC20BridgeSamplerContract extends BaseContract { 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.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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; @@ -744,6 +841,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { 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; @@ -751,6 +849,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as IERC20BridgeSamplerContract; @@ -852,25 +951,33 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Query batches of native orders and sample buy quotes on multiple DEXes at once. + * @param orders Batches of Native orders to query. + * @param orderSignatures Batches of Signatures for each respective order in + * `orders`. + * @param sources Address of each DEX. Passing in an unsupported DEX will + * throw. + * @param makerTokenAmounts Batches of Maker token sell amount for each sample. + * @returns ordersAndSamples How much taker asset can be filled by each order in `orders`. Taker amounts sold for each source at each maker token amount. First indexed by source index, then sample index + */ public queryBatchOrdersAndSampleBuys( - orders: Array< - 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; - }> - >, + 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[][], sources: string[], makerTokenAmounts: BigNumber[][], @@ -894,6 +1001,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { defaultBlock, ); const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue< Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> >(rawCallResult); @@ -908,25 +1016,33 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Query batches of native orders and sample sell quotes on multiple DEXes at once. + * @param orders Batches of Native orders to query. + * @param orderSignatures Batches of Signatures for each respective order in + * `orders`. + * @param sources Address of each DEX. Passing in an unsupported DEX will + * throw. + * @param takerTokenAmounts Batches of Taker token sell amount for each sample. + * @returns ordersAndSamples How much taker asset can be filled by each order in `orders`. Maker amounts bought for each source at each taker token amount. First indexed by source index, then sample index. + */ public queryBatchOrdersAndSampleSells( - orders: Array< - 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; - }> - >, + 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[][], sources: string[], takerTokenAmounts: BigNumber[][], @@ -950,6 +1066,7 @@ export class IERC20BridgeSamplerContract extends BaseContract { defaultBlock, ); const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); return abiEncoder.strictDecodeReturnValue< Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> >(rawCallResult); diff --git a/packages/contract-wrappers/src/generated-wrappers/lib_transaction_decoder.ts b/packages/contract-wrappers/src/generated-wrappers/lib_transaction_decoder.ts deleted file mode 100644 index 009ced047d..0000000000 --- a/packages/contract-wrappers/src/generated-wrappers/lib_transaction_decoder.ts +++ /dev/null @@ -1,367 +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, -} 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, 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:no-parameter-reassignment -// tslint:disable-next-line:class-name -export class LibTransactionDecoderContract extends BaseContract { - /** - * @ignore - */ - public static deployedBytecode = - '0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80636f83188e14610030575b600080fd5b61004361003e3660046113f4565b61005c565b604051610053949392919061176e565b60405180910390f35b60608080806000610073868263ffffffff610ba616565b90506001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156100e4576040518060400160405280601181526020017f626174636843616e63656c4f7264657273000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9694a402000000000000000000000000000000000000000000000000000000001415610153576040518060400160405280600f81526020017f626174636846696c6c4f72646572730000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f8ea8dfe40000000000000000000000000000000000000000000000000000000014156101c2576040518060400160405280601681526020017f626174636846696c6c4f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167fbeee2e14000000000000000000000000000000000000000000000000000000001415610231576040518060400160405280601581526020017f626174636846696c6c4f724b696c6c4f72646572730000000000000000000000815250945061067c565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156102a0576040518060400160405280600b81526020017f63616e63656c4f72646572000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000141561030f576040518060400160405280600981526020017f66696c6c4f726465720000000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000141561037e576040518060400160405280600f81526020017f66696c6c4f724b696c6c4f726465720000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f78d29ac10000000000000000000000000000000000000000000000000000000014156103ed576040518060400160405280601681526020017f6d61726b65744275794f72646572734e6f5468726f7700000000000000000000815250945061067c565b6001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000141561045c576040518060400160405280601781526020017f6d61726b657453656c6c4f72646572734e6f5468726f77000000000000000000815250945061067c565b6001600160e01b031981167f8bc8efb30000000000000000000000000000000000000000000000000000000014156104cb576040518060400160405280601981526020017f6d61726b65744275794f726465727346696c6c4f724b696c6c00000000000000815250945061067c565b6001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000141561053a576040518060400160405280601a81526020017f6d61726b657453656c6c4f726465727346696c6c4f724b696c6c000000000000815250945061067c565b6001600160e01b031981167f88ec79fb0000000000000000000000000000000000000000000000000000000014156105a9576040518060400160405280600b81526020017f6d617463684f7264657273000000000000000000000000000000000000000000815250945061067c565b6001600160e01b031981167f4f9559b100000000000000000000000000000000000000000000000000000000148061060a57506001600160e01b031981167f2280c91000000000000000000000000000000000000000000000000000000000145b1561064a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106419061186d565b60405180910390fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064190611836565b6001600160e01b031981167fdedfc1f10000000000000000000000000000000000000000000000000000000014156107215785516106c490879060049063ffffffff610be916565b8060200190516106d79190810190611289565b604080516000808252602082019092529195505b5060408051600080825260208201909252919450610719565b60608152602001906001900390816107045790505b509150610b9e565b6001600160e01b031981167fbeee2e1400000000000000000000000000000000000000000000000000000000148061078257506001600160e01b031981167f9694a40200000000000000000000000000000000000000000000000000000000145b806107b657506001600160e01b031981167f8ea8dfe400000000000000000000000000000000000000000000000000000000145b156107d0576107c486610c70565b91955093509150610b9e565b6001600160e01b031981167f2da629870000000000000000000000000000000000000000000000000000000014156108b85760408051600180825281830190925290816020015b61081f610f3d565b815260200190600190039081610817575050865190945061084a90879060049063ffffffff610be916565b80602001905161085d919081019061146b565b8460008151811061086a57fe5b602002602001018190525060006040519080825280602002602001820160405280156106eb578160200160208202803883390190505060408051600080825260208201909252919450610719565b6001600160e01b031981167fe14b58c400000000000000000000000000000000000000000000000000000000148061091957506001600160e01b031981167f9b44d55600000000000000000000000000000000000000000000000000000000145b15610927576107c486610cac565b6001600160e01b031981167f78d29ac100000000000000000000000000000000000000000000000000000000148061098857506001600160e01b031981167f369da09900000000000000000000000000000000000000000000000000000000145b806109bc57506001600160e01b031981167f8bc8efb300000000000000000000000000000000000000000000000000000000145b806109f057506001600160e01b031981167fa6c3bf3300000000000000000000000000000000000000000000000000000000145b156109fe576107c486610da6565b6001600160e01b031981167f88ec79fb000000000000000000000000000000000000000000000000000000001415610b9e57610a38610f3d565b610a40610f3d565b606080610a5a60048b518c610be99092919063ffffffff16565b806020019051610a6d919081019061149e565b604080516002808252606082019092529498509296509094509250816020015b610a95610f3d565b815260200190600190039081610a8d5790505097508388600081518110610ab857fe5b60200260200101819052508288600181518110610ad157fe5b602090810291909101015260408051600280825260608201909252908160200160208202803883390190505096508360a0015187600081518110610b1157fe5b6020026020010181815250508260a0015187600181518110610b2f57fe5b60209081029190910101526040805160028082526060820190925290816020015b6060815260200190600190039081610b505790505095508186600081518110610b7557fe5b60200260200101819052508086600181518110610b8e57fe5b6020026020010181905250505050505b509193509193565b60008160040183511015610bcc57610bcc610bc76003855185600401610e1a565b610e89565b5060208183018101519101906001600160e01b0319165b92915050565b606081831115610c0257610c02610bc760008585610e1a565b8351821115610c1b57610c1b610bc76001848751610e1a565b8282036040519080825280601f01601f191660200182016040528015610c48576020820181803883390190505b509050610c69610c5782610e91565b84610c6187610e91565b018351610e97565b9392505050565b6060806060610c8c6004855186610be99092919063ffffffff16565b806020019051610c9f91908101906112c4565b9196909550909350915050565b60408051600180825281830190925260609182918291816020015b610ccf610f3d565b815260200190600190039081610cc75750506040805160018082528183019092529194506020808301908038833901905050604080516001808252818301909252919350816020015b6060815260200190600190039081610d185750508451909150610d4590859060049063ffffffff610be916565b806020019051610d589190810190611546565b85600081518110610d6557fe5b6020026020010185600081518110610d7957fe5b6020026020010185600081518110610d8d57fe5b6020908102919091010192909252919052529193909250565b604080516001808252818301909252606091829182916020808301908038833950508551919350610de29186915060049063ffffffff610be916565b806020019051610df591908101906113a1565b84518590600090610e0257fe5b60209081029190910101919091529095929450925050565b6060632800659560e01b848484604051602401610e399392919061174c565b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b03199093169290921790915290509392505050565b805160208201fd5b60200190565b6020811015610ec1576001816020036101000a038019835116818551168082178652505050610f38565b82821415610ece57610f38565b82821115610f085760208103905080820181840181515b82851015610f00578451865260209586019590940193610ee5565b905250610f38565b60208103905080820181840183515b81861215610f335782518252601f199283019290910190610f17565b855250505b505050565b604051806101c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001606081526020016060815260200160608152602001606081525090565b805173ffffffffffffffffffffffffffffffffffffffff81168114610be357600080fd5b600082601f830112611038578081fd5b815161104b611046826118cb565b6118a4565b8181529150602080830190840160005b838110156110885761107387602084518901016110ed565b8352602092830192919091019060010161105b565b5050505092915050565b600082601f8301126110a2578081fd5b81516110b0611046826118cb565b8181529150602080830190840160005b83811015611088576110d8876020845189010161113a565b835260209283019291909101906001016110c0565b600082601f8301126110fd578081fd5b815161110b611046826118eb565b915080825283602082850101111561112257600080fd5b611133816020840160208601611918565b5092915050565b60006101c080838503121561114d578182fd5b611156816118a4565b9150506111638383611004565b81526111728360208401611004565b60208201526111848360408401611004565b60408201526111968360608401611004565b60608201526080820151608082015260a082015160a082015260c082015160c082015260e082015160e08201526101008083015181830152506101208083015181830152506101408083015167ffffffffffffffff808211156111f857600080fd5b611204868387016110ed565b8385015261016092508285015191508082111561122057600080fd5b61122c868387016110ed565b8385015261018092508285015191508082111561124857600080fd5b611254868387016110ed565b838501526101a092508285015191508082111561127057600080fd5b5061127d858286016110ed565b82840152505092915050565b60006020828403121561129a578081fd5b815167ffffffffffffffff8111156112b0578182fd5b6112bc84828501611092565b949350505050565b6000806000606084860312156112d8578182fd5b835167ffffffffffffffff808211156112ef578384fd5b6112fb87838801611092565b9450602091508186015181811115611311578485fd5b80870188601f820112611322578586fd5b80519150611332611046836118cb565b82815284810190828601868502840187018c101561134e578889fd5b8893505b84841015611370578051835260019390930192918601918601611352565b5060408a015190975094505050508082111561138a578283fd5b5061139786828701611028565b9150509250925092565b6000806000606084860312156113b5578283fd5b835167ffffffffffffffff808211156113cc578485fd5b6113d887838801611092565b945060208601519350604086015191508082111561138a578283fd5b600060208284031215611405578081fd5b813567ffffffffffffffff81111561141b578182fd5b80830184601f82011261142c578283fd5b8035915061143c611046836118eb565b828152856020848401011115611450578384fd5b82602083016020830137918201602001929092529392505050565b60006020828403121561147c578081fd5b815167ffffffffffffffff811115611492578182fd5b6112bc8482850161113a565b600080600080608085870312156114b3578081fd5b845167ffffffffffffffff808211156114ca578283fd5b6114d68883890161113a565b955060208701519150808211156114eb578283fd5b6114f78883890161113a565b9450604087015191508082111561150c578283fd5b611518888389016110ed565b9350606087015191508082111561152d578283fd5b5061153a878288016110ed565b91505092959194509250565b60008060006060848603121561155a578283fd5b835167ffffffffffffffff80821115611571578485fd5b61157d8783880161113a565b9450602086015193506040860151915080821115611599578283fd5b50611397868287016110ed565b60006101c06115b68484516116af565b60208301516115c860208601826116af565b5060408301516115db60408601826116af565b5060608301516115ee60608601826116af565b506080830151608085015260a083015160a085015260c083015160c085015260e083015160e085015261010080840151818601525061012080840151818601525061014080840151828287015261164783870182611720565b915050610160915081840151858203838701526116648282611720565b9250505061018080840151858303828701526116808382611720565b9150506101a09150818401518582038387015261169d8282611720565b9695505050505050565b815260200190565b73ffffffffffffffffffffffffffffffffffffffff169052565b600081518084526020840180819550602083028101915060208501845b848110156117145782840388526116fe848351611720565b60209889019890945091909101906001016116e6565b50919695505050505050565b60008151808452611738816020860160208601611918565b601f01601f19169290920160200192915050565b606081016008851061175a57fe5b938152602081019290925260409091015290565b6000608082526117816080830187611720565b602083820381850152818751611797818561190f565b91508193508281028201838a01865b838110156117d05786830385526117be8383516115a6565b948601949250908501906001016117a6565b50508681036040880152809450885192506117eb838261190f565b94505050818701845b82811015611815576118078583516116a7565b9450908301906001016117f4565b50505050828103606084015261182b81856116c9565b979650505050505050565b60208082526019908201527f554e4b4e4f574e5f46554e4354494f4e5f53454c4543544f5200000000000000604082015260600190565b6020808252600d908201527f554e494d504c454d454e54454400000000000000000000000000000000000000604082015260600190565b60405181810167ffffffffffffffff811182821017156118c357600080fd5b604052919050565b600067ffffffffffffffff8211156118e1578081fd5b5060209081020190565b600067ffffffffffffffff821115611901578081fd5b50601f01601f191660200190565b90815260200190565b60005b8381101561193357818101518382015260200161191b565b83811115611942576000848401525b5050505056fea365627a7a72315820884abdfe69fd82b726a34318b3e10d0da6e8c516e328d10258429ee105f0ad396c6578706572696d656e74616cf564736f6c63430005100040'; - public static contractName = 'LibTransactionDecoder'; - 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 LibTransactionDecoderContract.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(`LibTransactionDecoder successfully deployed at ${txReceipt.contractAddress}`); - const contractInstance = new LibTransactionDecoderContract( - 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: 'transactionData', - type: 'bytes', - }, - ], - name: 'decodeZeroExTransactionData', - outputs: [ - { - name: 'functionName', - type: 'string', - }, - { - 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: 'takerAssetFillAmounts', - type: 'uint256[]', - }, - { - name: 'signatures', - type: 'bytes[]', - }, - ], - payable: false, - stateMutability: 'pure', - type: 'function', - }, - ] as ContractAbi; - return abi; - } - - public getFunctionSignature(methodName: string): string { - const index = this._methodABIIndex[methodName]; - const methodAbi = LibTransactionDecoderContract.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 LibTransactionDecoderContract; - 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 LibTransactionDecoderContract; - 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 LibTransactionDecoderContract; - const abiEncoder = self._lookupAbiEncoder(functionSignature); - return abiEncoder.getSelector(); - } - - /** - * Decodes the call data for an Exchange contract method call. - * @param transactionData ABI-encoded calldata for an Exchange contract - * method call. - * @returns The name of the function called, and the parameters it was given. For single-order fills and cancels, the arrays will have just one element. - */ - public decodeZeroExTransactionData( - transactionData: string, - ): ContractFunctionObj< - [ - string, - 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; - }>, - BigNumber[], - string[] - ] - > { - const self = (this as any) as LibTransactionDecoderContract; - assert.isString('transactionData', transactionData); - const functionSignature = 'decodeZeroExTransactionData(bytes)'; - - return { - async callAsync( - callData: Partial = {}, - defaultBlock?: BlockParam, - ): Promise< - [ - string, - 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; - }>, - BigNumber[], - string[] - ] - > { - BaseContract._assertCallParams(callData, defaultBlock); - const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); - const abiEncoder = self._lookupAbiEncoder(functionSignature); - BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); - return abiEncoder.strictDecodeReturnValue< - [ - string, - 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; - }>, - BigNumber[], - string[] - ] - >(rawCallResult); - }, - getABIEncodedTransactionData(): string { - return self._strictEncodeArguments(functionSignature, [transactionData]); - }, - }; - } - - constructor( - address: string, - supportedProvider: SupportedProvider, - txDefaults?: Partial, - logDecodeDependencies?: { [contractName: string]: ContractAbi }, - deployedBytecode: string | undefined = LibTransactionDecoderContract.deployedBytecode, - ) { - super( - 'LibTransactionDecoder', - LibTransactionDecoderContract.ABI(), - address, - supportedProvider, - txDefaults, - logDecodeDependencies, - deployedBytecode, - ); - classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']); - LibTransactionDecoderContract.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/staking.ts b/packages/contract-wrappers/src/generated-wrappers/staking.ts index 585af60e1e..9dddd89f6d 100644 --- a/packages/contract-wrappers/src/generated-wrappers/staking.ts +++ b/packages/contract-wrappers/src/generated-wrappers/staking.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -165,6 +166,7 @@ export interface StakingUnstakeEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class StakingContract extends BaseContract { @@ -200,6 +202,43 @@ export class StakingContract extends BaseContract { } return StakingContract.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 StakingContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return StakingContract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -1583,12 +1622,64 @@ export class StakingContract extends BaseContract { 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 StakingContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = StakingContract.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 StakingContract; @@ -1596,6 +1687,7 @@ export class StakingContract extends BaseContract { 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 StakingContract; @@ -1603,6 +1695,7 @@ export class StakingContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as StakingContract; @@ -3430,6 +3523,7 @@ export class StakingContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -3437,12 +3531,14 @@ export class StakingContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The Staking contract event you would like to subscribe to. @@ -3468,6 +3564,7 @@ export class StakingContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/staking_proxy.ts b/packages/contract-wrappers/src/generated-wrappers/staking_proxy.ts index 4c962c3771..44929506da 100644 --- a/packages/contract-wrappers/src/generated-wrappers/staking_proxy.ts +++ b/packages/contract-wrappers/src/generated-wrappers/staking_proxy.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -71,6 +72,7 @@ export interface StakingProxyStakingContractAttachedToProxyEventArgs extends Dec export interface StakingProxyStakingContractDetachedFromProxyEventArgs extends DecodedLogArgs {} /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class StakingProxyContract extends BaseContract { @@ -114,6 +116,51 @@ export class StakingProxyContract extends BaseContract { _stakingContract, ); } + + public static async deployWithLibrariesFrom0xArtifactAsync( + artifact: ContractArtifact, + libraryArtifacts: { [libraryName: string]: ContractArtifact }, + supportedProvider: SupportedProvider, + txDefaults: Partial, + logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact }, + _stakingContract: string, + ): 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 StakingProxyContract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return StakingProxyContract.deployAsync( + bytecode, + abi, + provider, + txDefaults, + logDecodeDependenciesAbiOnly, + _stakingContract, + ); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -702,12 +749,64 @@ export class StakingProxyContract extends BaseContract { 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 StakingProxyContract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = StakingProxyContract.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 StakingProxyContract; @@ -715,6 +814,7 @@ export class StakingProxyContract extends BaseContract { 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 StakingProxyContract; @@ -722,6 +822,7 @@ export class StakingProxyContract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as StakingProxyContract; @@ -1546,6 +1647,7 @@ export class StakingProxyContract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -1553,12 +1655,14 @@ export class StakingProxyContract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The StakingProxy contract event you would like to subscribe to. @@ -1584,6 +1688,7 @@ export class StakingProxyContract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/generated-wrappers/weth9.ts b/packages/contract-wrappers/src/generated-wrappers/weth9.ts index 1a6d7cf648..a8bb7f825b 100644 --- a/packages/contract-wrappers/src/generated-wrappers/weth9.ts +++ b/packages/contract-wrappers/src/generated-wrappers/weth9.ts @@ -10,6 +10,7 @@ import { SubscriptionManager, PromiseWithTransactionHash, methodAbiToFunctionSignature, + linkLibrariesInBytecode, } from '@0x/base-contract'; import { schemas } from '@0x/json-schemas'; import { @@ -27,7 +28,7 @@ import { TxDataPayable, SupportedProvider, } from 'ethereum-types'; -import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils'; +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'; @@ -70,6 +71,7 @@ export interface WETH9WithdrawalEventArgs extends DecodedLogArgs { } /* istanbul ignore next */ +// tslint:disable:array-type // tslint:disable:no-parameter-reassignment // tslint:disable-next-line:class-name export class WETH9Contract extends BaseContract { @@ -105,6 +107,43 @@ export class WETH9Contract extends BaseContract { } return WETH9Contract.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 WETH9Contract._deployLibrariesAsync( + artifact, + libraryArtifacts, + new Web3Wrapper(provider), + txDefaults, + ); + const bytecode = linkLibrariesInBytecode(artifact.compilerOutput.evm.bytecode, libraryAddresses); + if (!hexUtils.isHex(bytecode)) { + throw new Error(`Bytecode for "${artifact.contractName}" was not fully linked.`); + } + return WETH9Contract.deployAsync(bytecode, abi, provider, txDefaults, logDecodeDependenciesAbiOnly); + } + public static async deployAsync( bytecode: string, abi: ContractAbi, @@ -438,12 +477,64 @@ export class WETH9Contract extends BaseContract { 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 WETH9Contract._deployLibrariesAsync( + libraryArtifact, + libraryArtifacts, + web3Wrapper, + txDefaults, + libraryAddresses, + ); + // Deploy this library. + const linkedLibraryBytecode = linkLibrariesInBytecode( + libraryArtifact.compilerOutput.evm.bytecode, + libraryAddresses, + ); + if (!hexUtils.isHex(linkedLibraryBytecode)) { + throw new Error(`Bytecode for library "${libraryArtifact.contractName}" was not fully linked.`); + } + 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 = WETH9Contract.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 WETH9Contract; @@ -451,6 +542,7 @@ export class WETH9Contract extends BaseContract { 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 WETH9Contract; @@ -458,6 +550,7 @@ export class WETH9Contract extends BaseContract { const abiDecodedCallData = abiEncoder.strictDecodeReturnValue(callData); return abiDecodedCallData; } + public getSelector(methodName: string): string { const functionSignature = this.getFunctionSignature(methodName); const self = (this as any) as WETH9Contract; @@ -857,6 +950,7 @@ export class WETH9Contract extends BaseContract { ); return subscriptionToken; } + /** * Cancel a subscription * @param subscriptionToken Subscription token returned by `subscribe()` @@ -864,12 +958,14 @@ export class WETH9Contract extends BaseContract { public unsubscribe(subscriptionToken: string): void { this._subscriptionManager.unsubscribe(subscriptionToken); } + /** * Cancels all existing subscriptions */ public unsubscribeAll(): void { this._subscriptionManager.unsubscribeAll(); } + /** * Gets historical logs without creating a subscription * @param eventName The WETH9 contract event you would like to subscribe to. @@ -895,6 +991,7 @@ export class WETH9Contract extends BaseContract { ); return logs; } + constructor( address: string, supportedProvider: SupportedProvider, diff --git a/packages/contract-wrappers/src/index.ts b/packages/contract-wrappers/src/index.ts index 1c0b138e53..afe2195848 100644 --- a/packages/contract-wrappers/src/index.ts +++ b/packages/contract-wrappers/src/index.ts @@ -81,7 +81,6 @@ export { StakingProxyStakingContractAttachedToProxyEventArgs, StakingProxyStakingContractDetachedFromProxyEventArgs, } from './generated-wrappers/staking_proxy'; -export { LibTransactionDecoderContract } from './generated-wrappers/lib_transaction_decoder'; export { BlockRange, SupportedProvider, diff --git a/packages/dev-utils/CHANGELOG.json b/packages/dev-utils/CHANGELOG.json index 67e28d742c..fec9586d46 100644 --- a/packages/dev-utils/CHANGELOG.json +++ b/packages/dev-utils/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "3.2.0", + "changes": [ + { + "note": "Refactor into public libraries.", + "pr": 2464 + } + ] + }, { "version": "3.1.1", "changes": [ diff --git a/packages/migrations/CHANGELOG.json b/packages/migrations/CHANGELOG.json index 4f5ba49d8c..01e5ad4187 100644 --- a/packages/migrations/CHANGELOG.json +++ b/packages/migrations/CHANGELOG.json @@ -1,4 +1,21 @@ [ + { + "version": "6.1.0", + "changes": [ + { + "note": "Update `DevUtils` deployment", + "pr": 2456 + }, + { + "note": "Remove `LibTransactionDecoder` deployment", + "pr": 2456 + }, + { + "note": "Use contract package artifacts in ganache migrations", + "pr": 2456 + } + ] + }, { "version": "6.0.0", "changes": [ diff --git a/packages/migrations/package.json b/packages/migrations/package.json index 3b60a7de84..a167ecdc5c 100644 --- a/packages/migrations/package.json +++ b/packages/migrations/package.json @@ -63,7 +63,6 @@ "dependencies": { "@0x/base-contract": "^6.1.0", "@0x/contract-addresses": "^4.3.0", - "@0x/contract-artifacts": "^3.4.0", "@0x/contract-wrappers": "^13.4.0", "@0x/contracts-asset-proxy": "^3.1.1", "@0x/contracts-coordinator": "^3.0.4", diff --git a/packages/migrations/src/migration.ts b/packages/migrations/src/migration.ts index 6674bb21e7..2b39e40078 100644 --- a/packages/migrations/src/migration.ts +++ b/packages/migrations/src/migration.ts @@ -1,7 +1,6 @@ import { ContractAddresses, getContractAddressesForChainOrThrow } from '@0x/contract-addresses'; -import * as artifacts from '@0x/contract-artifacts'; -import { ForwarderContract } from '@0x/contract-wrappers'; import { + artifacts as assetProxyArtifacts, ERC1155ProxyContract, ERC20BridgeProxyContract, ERC20ProxyContract, @@ -9,12 +8,17 @@ import { MultiAssetProxyContract, StaticCallProxyContract, } from '@0x/contracts-asset-proxy'; -import { CoordinatorContract, CoordinatorRegistryContract } from '@0x/contracts-coordinator'; -import { DevUtilsContract, LibTransactionDecoderContract } from '@0x/contracts-dev-utils'; -import { ERC1155MintableContract } from '@0x/contracts-erc1155'; -import { DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; -import { DummyERC721TokenContract } from '@0x/contracts-erc721'; -import { ExchangeContract } from '@0x/contracts-exchange'; +import { + artifacts as coordinatorArtifacts, + CoordinatorContract, + CoordinatorRegistryContract, +} from '@0x/contracts-coordinator'; +import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils'; +import { artifacts as erc1155Artifacts, ERC1155MintableContract } from '@0x/contracts-erc1155'; +import { artifacts as erc20Artifacts, DummyERC20TokenContract, WETH9Contract } from '@0x/contracts-erc20'; +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'; import { artifacts as stakingArtifacts, StakingProxyContract, @@ -28,6 +32,18 @@ import { SupportedProvider, TxData } from 'ethereum-types'; import { constants } from './utils/constants'; import { erc20TokenInfo, erc721TokenInfo } from './utils/token_info'; +const allArtifacts = { + ...assetProxyArtifacts, + ...coordinatorArtifacts, + ...devUtilsArtifacts, + ...erc1155Artifacts, + ...erc20Artifacts, + ...erc721Artifacts, + ...exchangeArtifacts, + ...forwarderArtifacts, + ...stakingArtifacts, +}; + /** * Creates and deploys all the contracts that are required for the latest * version of the 0x protocol. @@ -44,24 +60,24 @@ export async function runMigrationsAsync( // Proxies const erc20Proxy = await ERC20ProxyContract.deployFrom0xArtifactAsync( - artifacts.ERC20Proxy, + assetProxyArtifacts.ERC20Proxy, provider, txDefaults, - artifacts, + allArtifacts, ); const erc721Proxy = await ERC721ProxyContract.deployFrom0xArtifactAsync( - artifacts.ERC721Proxy, + assetProxyArtifacts.ERC721Proxy, provider, txDefaults, - artifacts, + allArtifacts, ); // ZRX const zrxToken = await DummyERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC20Token, + erc20Artifacts.DummyERC20Token, provider, txDefaults, - artifacts, + allArtifacts, '0x Protocol Token', 'ZRX', new BigNumber(18), @@ -69,14 +85,19 @@ export async function runMigrationsAsync( ); // Ether token - const etherToken = await WETH9Contract.deployFrom0xArtifactAsync(artifacts.WETH9, provider, txDefaults, artifacts); + const etherToken = await WETH9Contract.deployFrom0xArtifactAsync( + erc20Artifacts.WETH9, + provider, + txDefaults, + allArtifacts, + ); // Exchange const exchange = await ExchangeContract.deployFrom0xArtifactAsync( - artifacts.Exchange, + exchangeArtifacts.Exchange, provider, txDefaults, - artifacts, + allArtifacts, chainId, ); @@ -85,10 +106,10 @@ export async function runMigrationsAsync( const totalSupply = new BigNumber(1000000000000000000000000000); // tslint:disable-next-line:no-unused-variable const dummyErc20Token = await DummyERC20TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC20Token, + erc20Artifacts.DummyERC20Token, provider, txDefaults, - artifacts, + allArtifacts, token.name, token.symbol, token.decimals, @@ -99,34 +120,34 @@ export async function runMigrationsAsync( // ERC721 // tslint:disable-next-line:no-unused-variable const cryptoKittieToken = await DummyERC721TokenContract.deployFrom0xArtifactAsync( - artifacts.DummyERC721Token, + erc721Artifacts.DummyERC721Token, provider, txDefaults, - artifacts, + allArtifacts, erc721TokenInfo[0].name, erc721TokenInfo[0].symbol, ); // 1155 Asset Proxy const erc1155Proxy = await ERC1155ProxyContract.deployFrom0xArtifactAsync( - artifacts.ERC1155Proxy, + assetProxyArtifacts.ERC1155Proxy, provider, txDefaults, - artifacts, + allArtifacts, ); const staticCallProxy = await StaticCallProxyContract.deployFrom0xArtifactAsync( - artifacts.StaticCallProxy, + assetProxyArtifacts.StaticCallProxy, provider, txDefaults, - artifacts, + allArtifacts, ); const multiAssetProxy = await MultiAssetProxyContract.deployFrom0xArtifactAsync( - artifacts.MultiAssetProxy, + assetProxyArtifacts.MultiAssetProxy, provider, txDefaults, - artifacts, + allArtifacts, ); await erc20Proxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); @@ -152,45 +173,46 @@ export async function runMigrationsAsync( // CoordinatorRegistry const coordinatorRegistry = await CoordinatorRegistryContract.deployFrom0xArtifactAsync( - artifacts.CoordinatorRegistry, + coordinatorArtifacts.CoordinatorRegistry, provider, txDefaults, - artifacts, + allArtifacts, ); // Coordinator const coordinator = await CoordinatorContract.deployFrom0xArtifactAsync( - artifacts.Coordinator, + coordinatorArtifacts.Coordinator, provider, txDefaults, - artifacts, + allArtifacts, exchange.address, chainId, ); // Dev Utils - const devUtils = await DevUtilsContract.deployFrom0xArtifactAsync( - artifacts.DevUtils, + const devUtils = await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( + devUtilsArtifacts.DevUtils, + devUtilsArtifacts, provider, txDefaults, - artifacts, + allArtifacts, exchange.address, constants.NULL_ADDRESS, ); // tslint:disable-next-line:no-unused-variable const erc1155DummyToken = await ERC1155MintableContract.deployFrom0xArtifactAsync( - artifacts.ERC1155Mintable, + erc1155Artifacts.ERC1155Mintable, provider, txDefaults, - artifacts, + allArtifacts, ); const erc20BridgeProxy = await ERC20BridgeProxyContract.deployFrom0xArtifactAsync( - artifacts.ERC20BridgeProxy, + assetProxyArtifacts.ERC20BridgeProxy, provider, txDefaults, - {}, + allArtifacts, ); await exchange.registerAssetProxy(erc20BridgeProxy.address).awaitTransactionSuccessAsync(txDefaults); await erc20BridgeProxy.addAuthorizedAddress(exchange.address).awaitTransactionSuccessAsync(txDefaults); @@ -199,10 +221,10 @@ export async function runMigrationsAsync( const zrxProxy = erc20Proxy.address; const zrxVault = await ZrxVaultContract.deployFrom0xArtifactAsync( - artifacts.ZrxVault, + stakingArtifacts.ZrxVault, provider, txDefaults, - {}, + allArtifacts, zrxProxy, zrxToken.address, ); @@ -213,16 +235,16 @@ export async function runMigrationsAsync( stakingArtifacts.TestStaking, provider, txDefaults, - {}, + allArtifacts, etherToken.address, zrxVault.address, ); const stakingProxy = await StakingProxyContract.deployFrom0xArtifactAsync( - artifacts.StakingProxy, + stakingArtifacts.StakingProxy, provider, txDefaults, - {}, + allArtifacts, stakingLogic.address, ); @@ -245,23 +267,15 @@ export async function runMigrationsAsync( // in the constructor const { exchangeV2: exchangeV2Address } = getContractAddressesForChainOrThrow(chainId.toNumber()); const forwarder = await ForwarderContract.deployFrom0xArtifactAsync( - artifacts.Forwarder, + forwarderArtifacts.Forwarder, provider, txDefaults, - artifacts, + allArtifacts, exchange.address, exchangeV2Address || constants.NULL_ADDRESS, etherToken.address, ); - // LibTransactionDecoder - const libTransactionDecoder = await LibTransactionDecoderContract.deployFrom0xArtifactAsync( - artifacts.LibTransactionDecoder, - provider, - txDefaults, - artifacts, - ); - const contractAddresses = { erc20Proxy: erc20Proxy.address, erc721Proxy: erc721Proxy.address, @@ -273,7 +287,6 @@ export async function runMigrationsAsync( erc20BridgeProxy: erc20BridgeProxy.address, zeroExGovernor: constants.NULL_ADDRESS, forwarder: forwarder.address, - libTransactionDecoder: libTransactionDecoder.address, orderValidator: constants.NULL_ADDRESS, dutchAuction: constants.NULL_ADDRESS, coordinatorRegistry: coordinatorRegistry.address, diff --git a/packages/migrations/src/testnet_migrations.ts b/packages/migrations/src/testnet_migrations.ts index 445a6a0884..f5b6f45324 100644 --- a/packages/migrations/src/testnet_migrations.ts +++ b/packages/migrations/src/testnet_migrations.ts @@ -9,11 +9,7 @@ import { UniswapBridgeContract, } from '@0x/contracts-asset-proxy'; import { artifacts as coordinatorArtifacts, CoordinatorContract } from '@0x/contracts-coordinator'; -import { - artifacts as devUtilsArtifacts, - DevUtilsContract, - LibTransactionDecoderContract, -} from '@0x/contracts-dev-utils'; +import { artifacts as devUtilsArtifacts, DevUtilsContract } from '@0x/contracts-dev-utils'; import { artifacts as exchangeArtifacts, ExchangeContract } from '@0x/contracts-exchange'; import { artifacts as forwarderArtifacts, ForwarderContract } from '@0x/contracts-exchange-forwarder'; import { @@ -249,8 +245,9 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t ]); await submitAndExecuteTransactionAsync(governor, governor.address, batchTransactionData); - await DevUtilsContract.deployFrom0xArtifactAsync( + await DevUtilsContract.deployWithLibrariesFrom0xArtifactAsync( devUtilsArtifacts.DevUtils, + devUtilsArtifacts, provider, txDefaults, devUtilsArtifacts, @@ -276,13 +273,6 @@ export async function runMigrationsAsync(supportedProvider: SupportedProvider, t deployedAddresses.exchangeV2, deployedAddresses.etherToken, ); - - await LibTransactionDecoderContract.deployFrom0xArtifactAsync( - devUtilsArtifacts.LibTransactionDecoder, - provider, - txDefaults, - devUtilsArtifacts, - ); } (async () => {