diff --git a/contracts/erc20-bridge-sampler/CHANGELOG.json b/contracts/erc20-bridge-sampler/CHANGELOG.json index 220400b08f..cbaabc5d2b 100644 --- a/contracts/erc20-bridge-sampler/CHANGELOG.json +++ b/contracts/erc20-bridge-sampler/CHANGELOG.json @@ -17,6 +17,10 @@ { "note": "Use `searchBestRate` in Kyber samples. Return 0 when Uniswap/Eth2Dai reserve", "pr": 2575 + }, + { + "note": "Add UniswapV2", + "pr": 2595 } ] }, diff --git a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol index f5216c3a41..c34151262e 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol @@ -34,6 +34,7 @@ import "./IUniswapExchangeQuotes.sol"; import "./ICurve.sol"; import "./ILiquidityProvider.sol"; import "./ILiquidityProviderRegistry.sol"; +import "./IUniswapV2Router01.sol"; contract ERC20BridgeSampler is @@ -46,6 +47,8 @@ contract ERC20BridgeSampler is uint256 constant internal KYBER_CALL_GAS = 1500e3; // 1.5m /// @dev Gas limit for Uniswap calls. uint256 constant internal UNISWAP_CALL_GAS = 150e3; // 150k + /// @dev Gas limit for UniswapV2 calls. + uint256 constant internal UNISWAPV2_CALL_GAS = 150e3; // 150k /// @dev Base gas limit for Eth2Dai calls. uint256 constant internal ETH2DAI_CALL_GAS = 1000e3; // 1m /// @dev Base gas limit for Curve calls. Some Curves have multiple tokens @@ -645,6 +648,74 @@ contract ERC20BridgeSampler is } } + /// @dev Sample sell quotes from UniswapV2. + /// @param path Token route. + /// @param takerTokenAmounts Taker token sell amount for each sample. + /// @return makerTokenAmounts Maker amounts bought at each taker token + /// amount. + function sampleSellsFromUniswapV2( + address[] memory path, + uint256[] memory takerTokenAmounts + ) + public + view + returns (uint256[] memory makerTokenAmounts) + { + uint256 numSamples = takerTokenAmounts.length; + makerTokenAmounts = new uint256[](numSamples); + for (uint256 i = 0; i < numSamples; i++) { + (bool didSucceed, bytes memory resultData) = + _getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)( + abi.encodeWithSelector( + IUniswapV2Router01(0).getAmountsOut.selector, + takerTokenAmounts[i], + path + )); + uint256 buyAmount = 0; + if (didSucceed) { + // solhint-disable-next-line indent + buyAmount = abi.decode(resultData, (uint256[]))[path.length - 1]; + } else { + break; + } + makerTokenAmounts[i] = buyAmount; + } + } + + /// @dev Sample buy quotes from UniswapV2. + /// @param path Token route. + /// @param makerTokenAmounts Maker token buy amount for each sample. + /// @return takerTokenAmounts Taker amounts sold at each maker token + /// amount. + function sampleBuysFromUniswapV2( + address[] memory path, + uint256[] memory makerTokenAmounts + ) + public + view + returns (uint256[] memory takerTokenAmounts) + { + uint256 numSamples = makerTokenAmounts.length; + takerTokenAmounts = new uint256[](numSamples); + for (uint256 i = 0; i < numSamples; i++) { + (bool didSucceed, bytes memory resultData) = + _getUniswapV2Router01Address().staticcall.gas(UNISWAPV2_CALL_GAS)( + abi.encodeWithSelector( + IUniswapV2Router01(0).getAmountsIn.selector, + makerTokenAmounts[i], + path + )); + uint256 sellAmount = 0; + if (didSucceed) { + // solhint-disable-next-line indent + sellAmount = abi.decode(resultData, (uint256[]))[path.length - 1]; + } else { + break; + } + takerTokenAmounts[i] = sellAmount; + } + } + /// @dev Overridable way to get token decimals. /// @param tokenAddress Address of the token. /// @return decimals The decimal places for the token. diff --git a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol index 0084a720f0..521ca45cc2 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol @@ -240,4 +240,30 @@ interface IERC20BridgeSampler { external view returns (address providerAddress); + + /// @dev Sample sell quotes from UniswapV2. + /// @param path Token route. + /// @param takerTokenAmounts Taker token sell amount for each sample. + /// @return makerTokenAmounts Maker amounts bought at each taker token + /// amount. + function sampleSellsFromUniswapV2( + address[] calldata path, + uint256[] calldata takerTokenAmounts + ) + external + view + returns (uint256[] memory makerTokenAmounts); + + /// @dev Sample buy quotes from UniswapV2. + /// @param path Token route. + /// @param makerTokenAmounts Maker token buy amount for each sample. + /// @return takerTokenAmounts Taker amounts sold at each maker token + /// amount. + function sampleBuysFromUniswapV2( + address[] calldata path, + uint256[] calldata makerTokenAmounts + ) + external + view + returns (uint256[] memory takerTokenAmounts); } diff --git a/contracts/erc20-bridge-sampler/contracts/src/IUniswapV2Router01.sol b/contracts/erc20-bridge-sampler/contracts/src/IUniswapV2Router01.sol new file mode 100644 index 0000000000..b13ce3b67b --- /dev/null +++ b/contracts/erc20-bridge-sampler/contracts/src/IUniswapV2Router01.sol @@ -0,0 +1,33 @@ +/* + + Copyright 2019 ZeroEx Intl. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +pragma solidity ^0.5.9; + + +interface IUniswapV2Router01 { + + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts); + + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts); +} diff --git a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol index d714b90112..2968154c6c 100644 --- a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol @@ -25,6 +25,7 @@ import "../src/ERC20BridgeSampler.sol"; import "../src/IEth2Dai.sol"; import "../src/IDevUtils.sol"; import "../src/IKyberNetworkProxy.sol"; +import "../src/IUniswapV2Router01.sol"; library LibDeterministicQuotes { @@ -194,6 +195,55 @@ contract TestERC20BridgeSamplerUniswapExchange is } +contract TestERC20BridgeSamplerUniswapV2Router01 is + IUniswapV2Router01, + DeploymentConstants, + FailTrigger +{ + bytes32 constant private SALT = 0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1; + + // Deterministic `IUniswapV2Router01.getAmountsOut()`. + function getAmountsOut(uint256 amountIn, address[] calldata path) + external + view + returns (uint256[] memory amounts) + { + require(path.length >= 2, "PATH_TOO_SHORT"); + _revertIfShouldFail(); + amounts = new uint256[](path.length); + amounts[0] = amountIn; + for (uint256 i = 0; i < path.length - 1; ++i) { + amounts[i + 1] = LibDeterministicQuotes.getDeterministicSellQuote( + SALT, + path[i], + path[i + 1], + amounts[i] + ); + } + } + + // Deterministic `IUniswapV2Router01.getAmountsInt()`. + function getAmountsIn(uint256 amountOut, address[] calldata path) + external + view + returns (uint256[] memory amounts) + { + require(path.length >= 2, "PATH_TOO_SHORT"); + _revertIfShouldFail(); + amounts = new uint256[](path.length); + amounts[0] = amountOut; + for (uint256 i = 0; i < path.length - 1; ++i) { + amounts[i + 1] = LibDeterministicQuotes.getDeterministicBuyQuote( + SALT, + path[i], + path[i + 1], + amounts[i] + ); + } + } +} + + contract TestERC20BridgeSamplerKyberNetwork is IKyberNetwork, DeploymentConstants, @@ -325,6 +375,7 @@ contract TestERC20BridgeSampler is FailTrigger { TestERC20BridgeSamplerUniswapExchangeFactory public uniswap; + TestERC20BridgeSamplerUniswapV2Router01 public uniswapV2Router; TestERC20BridgeSamplerEth2Dai public eth2Dai; TestERC20BridgeSamplerKyberNetwork public kyber; @@ -332,6 +383,7 @@ contract TestERC20BridgeSampler is constructor() public ERC20BridgeSampler(address(this)) { uniswap = new TestERC20BridgeSamplerUniswapExchangeFactory(); + uniswapV2Router = new TestERC20BridgeSamplerUniswapV2Router01(); eth2Dai = new TestERC20BridgeSamplerEth2Dai(); kyber = new TestERC20BridgeSamplerKyberNetwork(); } @@ -399,6 +451,15 @@ contract TestERC20BridgeSampler is return address(uniswap); } + // Overriden to point to a custom contract. + function _getUniswapV2Router01Address() + internal + view + returns (address uniswapV2RouterAddress) + { + return address(uniswapV2Router); + } + // Overriden to point to a custom contract. function _getKyberNetworkProxyAddress() internal diff --git a/contracts/erc20-bridge-sampler/package.json b/contracts/erc20-bridge-sampler/package.json index 16a6893533..9fe7b39861 100644 --- a/contracts/erc20-bridge-sampler/package.json +++ b/contracts/erc20-bridge-sampler/package.json @@ -38,7 +38,7 @@ "config": { "publicInterfaceContracts": "ERC20BridgeSampler,IERC20BridgeSampler,ILiquidityProvider,ILiquidityProviderRegistry,DummyLiquidityProviderRegistry,DummyLiquidityProvider", "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.", - "abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|TestERC20BridgeSampler).json" + "abis": "./test/generated-artifacts/@(DummyLiquidityProvider|DummyLiquidityProviderRegistry|ERC20BridgeSampler|ICurve|IDevUtils|IERC20BridgeSampler|IEth2Dai|IKyberNetwork|IKyberNetworkProxy|ILiquidityProvider|ILiquidityProviderRegistry|IUniswapExchangeQuotes|IUniswapV2Router01|TestERC20BridgeSampler).json" }, "repository": { "type": "git", diff --git a/contracts/erc20-bridge-sampler/test/artifacts.ts b/contracts/erc20-bridge-sampler/test/artifacts.ts index 3e595b577e..e09dfbbde6 100644 --- a/contracts/erc20-bridge-sampler/test/artifacts.ts +++ b/contracts/erc20-bridge-sampler/test/artifacts.ts @@ -17,6 +17,7 @@ import * as IKyberNetworkProxy from '../test/generated-artifacts/IKyberNetworkPr import * as ILiquidityProvider from '../test/generated-artifacts/ILiquidityProvider.json'; import * as ILiquidityProviderRegistry from '../test/generated-artifacts/ILiquidityProviderRegistry.json'; import * as IUniswapExchangeQuotes from '../test/generated-artifacts/IUniswapExchangeQuotes.json'; +import * as IUniswapV2Router01 from '../test/generated-artifacts/IUniswapV2Router01.json'; import * as TestERC20BridgeSampler from '../test/generated-artifacts/TestERC20BridgeSampler.json'; export const artifacts = { DummyLiquidityProvider: DummyLiquidityProvider as ContractArtifact, @@ -31,5 +32,6 @@ export const artifacts = { ILiquidityProvider: ILiquidityProvider as ContractArtifact, ILiquidityProviderRegistry: ILiquidityProviderRegistry as ContractArtifact, IUniswapExchangeQuotes: IUniswapExchangeQuotes as ContractArtifact, + IUniswapV2Router01: IUniswapV2Router01 as ContractArtifact, TestERC20BridgeSampler: TestERC20BridgeSampler as ContractArtifact, }; diff --git a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts b/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts index 78254134a2..a289d10dde 100644 --- a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts +++ b/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts @@ -28,6 +28,7 @@ blockchainTests('erc20-bridge-sampler', env => { const KYBER_SALT = '0x0ff3ca9d46195c39f9a12afb74207b4970349fb3cfb1e459bbf170298d326bc7'; const ETH2DAI_SALT = '0xb713b61bb9bb2958a0f5d1534b21e94fc68c4c0c034b0902ed844f2f6cd1b4f7'; const UNISWAP_BASE_SALT = '0x1d6a6a0506b0b4a554b907a4c29d9f4674e461989d9c1921feb17b26716385ab'; + const UNISWAP_V2_SALT = '0xadc7fcb33c735913b8635927e66896b356a53a912ab2ceff929e60a04b53b3c1'; const ERC20_PROXY_ID = '0xf47261b0'; const INVALID_TOKEN_PAIR_ERROR = 'ERC20BridgeSampler/INVALID_TOKEN_PAIR'; const MAKER_TOKEN = randomAddress(); @@ -191,6 +192,22 @@ blockchainTests('erc20-bridge-sampler', env => { return quotes; } + function getDeterministicUniswapV2SellQuote(path: string[], sellAmount: BigNumber): BigNumber { + let bought = sellAmount; + for (let i = 0; i < path.length - 1; ++i) { + bought = getDeterministicSellQuote(UNISWAP_V2_SALT, path[i], path[i + 1], bought); + } + return bought; + } + + function getDeterministicUniswapV2BuyQuote(path: string[], buyAmount: BigNumber): BigNumber { + let sold = buyAmount; + for (let i = 0; i < path.length - 1; ++i) { + sold = getDeterministicBuyQuote(UNISWAP_V2_SALT, path[i], path[i + 1], sold); + } + return sold; + } + function getDeterministicFillableTakerAssetAmount(order: Order): BigNumber { const hash = getPackedHash(hexUtils.leftPad(order.salt)); const orderStatus = new BigNumber(hash).mod(100).toNumber() > 90 ? 5 : 3; @@ -926,6 +943,86 @@ blockchainTests('erc20-bridge-sampler', env => { }); }); + blockchainTests.resets('sampleSellsFromUniswapV2()', () => { + function predictSellQuotes(path: string[], sellAmounts: BigNumber[]): BigNumber[] { + return sellAmounts.map(a => getDeterministicUniswapV2SellQuote(path, a)); + } + + it('can return no quotes', async () => { + const quotes = await testContract.sampleSellsFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], []).callAsync(); + expect(quotes).to.deep.eq([]); + }); + + it('can quote token -> token', async () => { + const sampleAmounts = getSampleAmounts(TAKER_TOKEN); + const expectedQuotes = predictSellQuotes([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts); + const quotes = await testContract + .sampleSellsFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + + it('returns zero if token -> token fails', async () => { + const sampleAmounts = getSampleAmounts(TAKER_TOKEN); + const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT); + await enableFailTriggerAsync(); + const quotes = await testContract + .sampleSellsFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + + it('can quote token -> token -> token', async () => { + const intermediateToken = randomAddress(); + const sampleAmounts = getSampleAmounts(TAKER_TOKEN); + const expectedQuotes = predictSellQuotes([TAKER_TOKEN, intermediateToken, MAKER_TOKEN], sampleAmounts); + const quotes = await testContract + .sampleSellsFromUniswapV2([TAKER_TOKEN, intermediateToken, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + }); + + blockchainTests.resets('sampleBuysFromUniswapV2()', () => { + function predictBuyQuotes(path: string[], buyAmounts: BigNumber[]): BigNumber[] { + return buyAmounts.map(a => getDeterministicUniswapV2BuyQuote(path, a)); + } + + it('can return no quotes', async () => { + const quotes = await testContract.sampleBuysFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], []).callAsync(); + expect(quotes).to.deep.eq([]); + }); + + it('can quote token -> token', async () => { + const sampleAmounts = getSampleAmounts(MAKER_TOKEN); + const expectedQuotes = predictBuyQuotes([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts); + const quotes = await testContract + .sampleBuysFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + + it('returns zero if token -> token fails', async () => { + const sampleAmounts = getSampleAmounts(MAKER_TOKEN); + const expectedQuotes = _.times(sampleAmounts.length, () => constants.ZERO_AMOUNT); + await enableFailTriggerAsync(); + const quotes = await testContract + .sampleBuysFromUniswapV2([TAKER_TOKEN, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + + it('can quote token -> token -> token', async () => { + const intermediateToken = randomAddress(); + const sampleAmounts = getSampleAmounts(MAKER_TOKEN); + const expectedQuotes = predictBuyQuotes([TAKER_TOKEN, intermediateToken, MAKER_TOKEN], sampleAmounts); + const quotes = await testContract + .sampleBuysFromUniswapV2([TAKER_TOKEN, intermediateToken, MAKER_TOKEN], sampleAmounts) + .callAsync(); + expect(quotes).to.deep.eq(expectedQuotes); + }); + }); + describe('batchCall()', () => { it('can call one function', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN); diff --git a/contracts/erc20-bridge-sampler/test/wrappers.ts b/contracts/erc20-bridge-sampler/test/wrappers.ts index 94707cc529..d292624166 100644 --- a/contracts/erc20-bridge-sampler/test/wrappers.ts +++ b/contracts/erc20-bridge-sampler/test/wrappers.ts @@ -15,4 +15,5 @@ export * from '../test/generated-wrappers/i_kyber_network_proxy'; export * from '../test/generated-wrappers/i_liquidity_provider'; export * from '../test/generated-wrappers/i_liquidity_provider_registry'; export * from '../test/generated-wrappers/i_uniswap_exchange_quotes'; +export * from '../test/generated-wrappers/i_uniswap_v2_router01'; export * from '../test/generated-wrappers/test_erc20_bridge_sampler'; diff --git a/contracts/erc20-bridge-sampler/tsconfig.json b/contracts/erc20-bridge-sampler/tsconfig.json index 0000dc7c83..f0e03e1174 100644 --- a/contracts/erc20-bridge-sampler/tsconfig.json +++ b/contracts/erc20-bridge-sampler/tsconfig.json @@ -21,6 +21,7 @@ "test/generated-artifacts/ILiquidityProvider.json", "test/generated-artifacts/ILiquidityProviderRegistry.json", "test/generated-artifacts/IUniswapExchangeQuotes.json", + "test/generated-artifacts/IUniswapV2Router01.json", "test/generated-artifacts/TestERC20BridgeSampler.json" ], "exclude": ["./deploy/solc/solc_bin"] diff --git a/contracts/utils/CHANGELOG.json b/contracts/utils/CHANGELOG.json index f85e798567..89e7ba066d 100644 --- a/contracts/utils/CHANGELOG.json +++ b/contracts/utils/CHANGELOG.json @@ -17,6 +17,10 @@ { "note": "Add more solidity 0.6 contracts", "pr": 2545 + }, + { + "note": "Add UniswapV2 addresses to `DeploymentConstants`", + "pr": 2595 } ] }, diff --git a/contracts/utils/contracts/src/DeploymentConstants.sol b/contracts/utils/contracts/src/DeploymentConstants.sol index 30a6cd0fa9..9876792a04 100644 --- a/contracts/utils/contracts/src/DeploymentConstants.sol +++ b/contracts/utils/contracts/src/DeploymentConstants.sol @@ -32,6 +32,10 @@ contract DeploymentConstants { address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95; // /// @dev Kovan address of the `UniswapExchangeFactory` contract. // address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30; + /// @dev Mainnet address of the `UniswapV2Router01` contract. + address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a; + // /// @dev Kovan address of the `UniswapV2Router01` contract. + // address constant private UNISWAP_V2_ROUTER_01ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a; /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract. address constant private ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D; // /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract. @@ -93,6 +97,16 @@ contract DeploymentConstants { return UNISWAP_EXCHANGE_FACTORY_ADDRESS; } + /// @dev Overridable way to get the `UniswapV2Router01` address. + /// @return uniswapRouterAddress The `UniswapV2Router01` address. + function _getUniswapV2Router01Address() + internal + view + returns (address uniswapRouterAddress) + { + return UNISWAP_V2_ROUTER_01_ADDRESS; + } + /// @dev An overridable way to retrieve the Eth2Dai `MatchingMarket` contract. /// @return eth2daiAddress The Eth2Dai `MatchingMarket` contract. function _getEth2DaiAddress() diff --git a/packages/contract-artifacts/CHANGELOG.json b/packages/contract-artifacts/CHANGELOG.json index 34fa6665c4..4fcb5ab269 100644 --- a/packages/contract-artifacts/CHANGELOG.json +++ b/packages/contract-artifacts/CHANGELOG.json @@ -17,6 +17,14 @@ { "note": "Added `ERC20BridgeSampler.sampleBuysFromKyberNetwork`", "pr": 2551 + }, + { + "note": "Added `ERC20BridgeSampler.sampleBuysFromUniswapV2", + "pr": 2595 + }, + { + "note": "Added `ERC20BridgeSampler.sampleSellsFromUniswapV2", + "pr": 2595 } ] }, diff --git a/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json b/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json index acff27beab..b414fffcc1 100644 --- a/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json +++ b/packages/contract-artifacts/artifacts/ERC20BridgeSampler.json @@ -184,6 +184,18 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } + ], + "name": "sampleBuysFromUniswapV2", + "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -264,6 +276,18 @@ "payable": false, "stateMutability": "view", "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } + ], + "name": "sampleSellsFromUniswapV2", + "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], + "payable": false, + "stateMutability": "view", + "type": "function" } ], "devdoc": { @@ -346,6 +370,14 @@ }, "return": "takerTokenAmounts Taker amounts sold at each maker token amount." }, + "sampleBuysFromUniswapV2(address[],uint256[])": { + "details": "Sample buy quotes from UniswapV2.", + "params": { + "makerTokenAmounts": "Maker token buy amount for each sample.", + "path": "Token route." + }, + "return": "takerTokenAmounts Taker amounts sold at each maker token amount." + }, "sampleSellsFromCurve(address,int128,int128,uint256[])": { "details": "Sample sell quotes from Curve.", "params": { @@ -402,15 +434,23 @@ "takerTokenAmounts": "Taker token sell amount for each sample." }, "return": "makerTokenAmounts Maker amounts bought at each taker token amount." + }, + "sampleSellsFromUniswapV2(address[],uint256[])": { + "details": "Sample sell quotes from UniswapV2.", + "params": { + "path": "Token route.", + "takerTokenAmounts": "Taker token sell amount for each sample." + }, + "return": "makerTokenAmounts Maker amounts bought at each taker token amount." } } }, "evm": { "bytecode": { - "object": "0x60806040523480156200001157600080fd5b506040516200354b3803806200354b83398101604081905262000034916200005a565b600080546001600160a01b0319166001600160a01b03929092169190911790556200008a565b6000602082840312156200006c578081fd5b81516001600160a01b038116811462000083578182fd5b9392505050565b6134b1806200009a6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806364ee6ade1161009757806398cdafba1161006657806398cdafba146101ee5780639f76ad3514610201578063c7f7142e14610214578063d0eea06d14610234576100f5565b806364ee6ade1461019557806368be3cf2146101a85780636dd6b78d146101c85780638b123a02146101db576100f5565b80634cb8e253116100d35780634cb8e2531461014957806358306ba01461015c57806359f515d01461016f57806360ee052a14610182576100f5565b80631796fb87146100fa578063354152a3146101235780634703a7e614610136575b600080fd5b61010d610108366004612cd2565b610247565b60405161011a91906131b7565b60405180910390f35b61010d610131366004612cd2565b610418565b61010d610144366004612c00565b6105d2565b61010d610157366004612c00565b6107ae565b61010d61016a366004612b08565b610991565b61010d61017d366004612d7c565b610a28565b61010d610190366004612c00565b610ad1565b61010d6101a3366004612c00565b610d91565b6101bb6101b6366004612d10565b610f57565b60405161011a9190613139565b61010d6101d6366004612c00565b611096565b61010d6101e9366004612d7c565b61133e565b61010d6101fc366004612b7b565b611617565b61010d61020f366004612b08565b611653565b610227610222366004612abe565b611857565b60405161011a9190613010565b61010d610242366004612c60565b611992565b606060008251905080604051908082528060200260200182016040528015610279578160200160208202803883390190505b50915060005b8181101561040e57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff16630e71d1b9905060e01b8a8a8a88815181106102d657fe5b60200260200101516040516024016102f0939291906131fa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516103799190612ff4565b6000604051808303818686fa925050503d80600081146103b5576040519150601f19603f3d011682016040523d82523d6000602084013e6103ba565b606091505b509092509050600082156103e357818060200190516103dc9190810190612f2d565b90506103eb565b50505061040e565b808685815181106103f857fe5b602090810291909101015250505060010161027f565b5050949350505050565b60606000825190508060405190808252806020026020018201604052801561044a578160200160208202803883390190505b50915060005b8181101561040e57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff166307211ef7905060e01b8a8a8a88815181106104a757fe5b60200260200101516040516024016104c1939291906131fa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161054a9190612ff4565b6000604051808303818686fa925050503d8060008114610586576040519150601f19603f3d011682016040523d82523d6000602084013e61058b565b606091505b509092509050600082156103e357818060200190516105ad9190810190612f2d565b9050808685815181106105bc57fe5b6020908102919091010152505050600101610450565b60606105de83856119c3565b8151604080518281526020808402820101909152818015610609578160200160208202803883390190505b50915060005b818110156107a55760006060610623611a36565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a888151811061066d57fe5b6020026020010151604051602401610687939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516107109190612ff4565b6000604051808303818686fa925050503d806000811461074c576040519150601f19603f3d011682016040523d82523d6000602084013e610751565b606091505b5090925090506000821561077a57818060200190516107739190810190612f2d565b9050610782565b5050506107a5565b8086858151811061078f57fe5b602090810291909101015250505060010161060f565b50509392505050565b60606107ba83856119c3565b81516040805182815260208084028201019091528180156107e5578160200160208202803883390190505b50915060006107f2611a4e565b9050600080805b84811015610985578373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16148061086657508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b1561089357610889898989848151811061087c57fe5b6020026020010151611a66565b9093509150610965565b6108a4898589848151811061087c57fe5b909350915082156109655760006108bc858a86611a66565b909450905073ffffffffffffffffffffffffffffffffffffffff83167331e085afd48a1d6e51cc193153d625e8f0514c7f1480610922575073ffffffffffffffffffffffffffffffffffffffff8316731e158c0e93c30d24e918ef83d1e0be23595c3c0f145b801561095957508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b1561096357600093505b505b8286828151811061097257fe5b60209081029190910101526001016107f9565b50505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806109f857508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610a0257610a20565b6060610a0f868585610d91565b9050610a1c848683610d91565b9150505b949350505050565b6060610a34838361133e565b905060005b8351811015610aca57818181518110610a4e57fe5b6020026020010151600014610ac257610aa9828281518110610a6c57fe5b6020026020010151858381518110610a8057fe5b602002602001015160a00151868481518110610a9857fe5b602002602001015160800151611dda565b828281518110610ab557fe5b6020026020010181815250505b600101610a39565b5092915050565b6060610add83856119c3565b8151604080518281526020808402820101909152818015610b08578160200160208202803883390190505b5091506000610b15611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610b5557610b5086611e1c565b610b58565b60005b90506000610b64611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610ba457610b9f86611e1c565b610ba7565b60005b905060005b83811015610d86576001610bbe611a4e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610c55578651610c349085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b6020026020010151611eb4565b878481518110610c4057fe5b60200260200101819350828152505050610d72565b610c5d611a4e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610cc6578651610c349084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b8651600090610cff9085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610c2757fe5b925090508015610d5557610d34857f2640f62c0000000000000000000000000000000000000000000000000000000083611eb4565b888581518110610d4057fe5b60200260200101819450828152505050610d70565b6000878481518110610d6357fe5b6020026020010181815250505b505b80610d7d5750610d86565b50600101610bac565b505050509392505050565b6060610d9d83856119c3565b8151604080518281526020808402820101909152818015610dc8578160200160208202803883390190505b50915060005b818110156107a55760006060610de2611a36565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a8881518110610e2c57fe5b6020026020010151604051602401610e46939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610ecf9190612ff4565b6000604051808303818686fa925050503d8060008114610f0b576040519150601f19603f3d011682016040523d82523d6000602084013e610f10565b606091505b5090925090506000821561077a5781806020019051610f329190810190612f2d565b905080868581518110610f4157fe5b6020908102919091010152505050600101610dce565b604080518281526020808402820101909152606090828015610f8d57816020015b6060815260200190600190039081610f785790505b50905060005b808314610aca576000606030868685818110610fab57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136849003018112610fe557600080fd5b9091016020810191503567ffffffffffffffff81111561100457600080fd5b3681900382131561101457600080fd5b604051611022929190612fe4565b600060405180830381855afa9150503d806000811461105d576040519150601f19603f3d011682016040523d82523d6000602084013e611062565b606091505b50915091508161107457805160208201fd5b8084848151811061108157fe5b60209081029190910101525050600101610f93565b60606110a283856119c3565b81516040805182815260208084028201019091528180156110cd578160200160208202803883390190505b50915060006110da611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461111a5761111586611e1c565b61111d565b60005b90506000611129611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146111695761116486611e1c565b61116c565b60005b905060005b83811015610d86576001611183611a4e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561120d5786516111ec9085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b8784815181106111f857fe5b6020026020010181935082815250505061132a565b611215611a4e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16141561127e5786516111ec9084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b86516000906112b79086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610c2757fe5b92509050801561130d576112ec847fcd7724c30000000000000000000000000000000000000000000000000000000083611eb4565b8885815181106112f857fe5b60200260200101819450828152505050611328565b600087848151811061131b57fe5b6020026020010181815250505b505b806113355750610d86565b50600101611171565b6060825160405190808252806020026020018201604052801561136b578160200160208202803883390190505b506000805491925073ffffffffffffffffffffffffffffffffffffffff909116905b8451811461160f578381815181106113a157fe5b602002602001015151600014806113cf57508481815181106113bf57fe5b6020026020010151608001516000145b806113f157508481815181106113e157fe5b602002602001015160a001516000145b1561141557600083828151811061140457fe5b602002602001018181525050611607565b600060608373ffffffffffffffffffffffffffffffffffffffff166207a1208573ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b89868151811061146157fe5b602002602001015189878151811061147557fe5b602002602001015160405160240161148e929190613275565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516115179190612ff4565b6000604051808303818686fa925050503d8060008114611553576040519150601f19603f3d011682016040523d82523d6000602084013e611558565b606091505b50915091508161158357600085848151811061157057fe5b6020026020010181815250505050611607565b61158b61275c565b600080838060200190516115a29190810190612ec0565b919450925090506003835160068111156115b857fe5b1415806115c3575080155b156115e75760008887815181106115d657fe5b602002602001018181525050611601565b818887815181106115f457fe5b6020026020010181815250505b50505050505b60010161138d565b505092915050565b6060611647858585857f9f76ad35000000000000000000000000000000000000000000000000000000008b611ffc565b90505b95945050505050565b606060008251905080604051908082528060200260200182016040528015611685578160200160208202803883390190505b5091506000611695878787611857565b905073ffffffffffffffffffffffffffffffffffffffff81166116ba5750610a209050565b60005b8281101561184c57600060608373ffffffffffffffffffffffffffffffffffffffff1662030d40600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b888151811061171457fe5b602002602001015160405160240161172e939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516117b79190612ff4565b6000604051808303818686fa925050503d80600081146117f3576040519150601f19603f3d011682016040523d82523d6000602084013e6117f8565b606091505b50909250905060008215611821578180602001905161181a9190810190612f2d565b9050611829565b50505061184c565b8087858151811061183657fe5b60209081029190910101525050506001016116bd565b505050949350505050565b6040516000906060907f153f599700000000000000000000000000000000000000000000000000000000906118929086908690602401613031565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff168360405161191a9190612ff4565b600060405180830381855afa9150503d8060008114611955576040519150601f19603f3d011682016040523d82523d6000602084013e61195a565b606091505b509150915081801561196d575080516020145b156119875761197d81600c6121c3565b935050505061198b565b5050505b9392505050565b606061164a858585857f4cb8e253000000000000000000000000000000000000000000000000000000006000611ffc565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2990613218565b60405180910390fd5b5050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6000806000611a73611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611aab5785611ac1565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611acd611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611b055785611b1b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611b2888612208565b60ff1690506000611b3888612208565b60ff16905060006060611b49612213565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4f61ff8b00000000000000000000000000000000000000000000000000000000179052905173ffffffffffffffffffffffffffffffffffffffff929092169162030d4091611bc991612ff4565b6000604051808303818686fa925050503d8060008114611c05576040519150601f19603f3d011682016040523d82523d6000602084013e611c0a565b606091505b509150915081611c27575060009650869550611dd2945050505050565b600081806020019051611c3d9190810190612a75565b90508073ffffffffffffffffffffffffffffffffffffffff166216e360600073ffffffffffffffffffffffffffffffffffffffff16630c235d96905060e01b89898e6000604051602401611c949493929190613103565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611d1d9190612ff4565b6000604051808303818686fa925050503d8060008114611d59576040519150601f19603f3d011682016040523d82523d6000602084013e611d5e565b606091505b5090935091506000808415611d8a5783806020019051611d819190810190612a91565b92509050611da0565b5060009950899850611dd2975050505050505050565b670de0b6b3a764000087600a0a87600a0a8e85020281611dbc57fe5b0481611dc457fe5b049a50985050505050505050505b935093915050565b6000610a2083611e10611df482600163ffffffff61222b16565b611e04888763ffffffff61224a16565b9063ffffffff61227b16565b9063ffffffff61229716565b6000611e266122c1565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b8152600401611e5e9190613010565b60206040518083038186803b158015611e7657600080fd5b505afa158015611e8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611eae9190810190612a75565b92915050565b60008073ffffffffffffffffffffffffffffffffffffffff8516611ed757611dd2565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f08686604051602401611f0691906133c9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611f8f9190612ff4565b6000604051808303818686fa925050503d8060008114611fcb576040519150601f19603f3d011682016040523d82523d6000602084013e611fd0565b606091505b5090925090508115611ff35780806020019051611ff09190810190612f2d565b92505b50935093915050565b606061200886886119c3565b8451612013576121b9565b60008060008751604051908082528060200260200182016040528015612043578160200160208202803883390190505b509350612067898b8a60008151811061205857fe5b602002602001015189896122d9565b92508261207757506121b9915050565b6120848a8a8589896122d9565b91508161209457506121b9915050565b60005b88518110156121b45760005b8860200151811015612176576120cd8a83815181106120be57fe5b60200260200101518587611dda565b94506120e489600001516127100161271087611dda565b945060006120f58d8d888c8c6122d9565b9050806121025750612176565b8094508a838151811061211157fe5b6020026020010151851061216d5760008b848151811061212d57fe5b60200260200101518c858151811061214157fe5b60200260200101518703612710028161215657fe5b0490508a60000151811161216b575050612176565b505b506001016120a3565b5061219589828151811061218657fe5b60200260200101518486611dda565b8582815181106121a157fe5b6020908102919091010152600101612097565b505050505b9695505050505050565b600081601401835110156121e9576121e96121e4600485518560140161258e565b612633565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000611eae8261263b565b73818e6fecd516ecc3849daf6845e3ec868087b75590565b600082821115612244576122446121e46002858561270c565b50900390565b60008261225957506000611eae565b8282028284828161226657fe5b041461198b5761198b6121e46001868661270c565b60008282018381101561198b5761198b6121e46000868661270c565b6000816122ad576122ad6121e46003858561270c565b60008284816122b857fe5b04949350505050565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b604080516001808252818301909252600091606091829160208083019080388339019050509050858160008151811061230e57fe5b60209081029190910101527fffffffff0000000000000000000000000000000000000000000000000000000085167f4cb8e25300000000000000000000000000000000000000000000000000000000141561241e576040517f4cb8e253000000000000000000000000000000000000000000000000000000009061239a908a908a908590602401613099565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506124d7565b6040517f9f76ad3500000000000000000000000000000000000000000000000000000000906124579086908b908b908690602401613058565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291505b600060603073ffffffffffffffffffffffffffffffffffffffff16846040516125009190612ff4565b600060405180830381855afa9150503d806000811461253b576040519150601f19603f3d011682016040523d82523d6000602084013e612540565b606091505b50915091508161255757600094505050505061164a565b8080602001905161256b9190810190612e2d565b60008151811061257757fe5b602002602001015194505050505095945050505050565b6060632800659560e01b8484846040516024016125ad939291906131ec565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce5670000000000000000000000000000000000000000000000000000000081525060405161269f9190612ff4565b600060405180830381855afa9150503d80600081146126da576040519150601f19603f3d011682016040523d82523d6000602084013e6126df565b606091505b50915091508180156126f2575080516020145b156127055761270281600061272b565b92505b5050919050565b606063e946c1bb60e01b8484846040516024016125ad939291906131ca565b600061198b838360008160200183511015612753576127536121e4600585518560200161258e565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b8035611eae81613449565b600082601f830112612799578081fd5b81356127ac6127a7826133f9565b6133d2565b8181529150602080830190840160005b838110156127e9576127d4876020843589010161285c565b835260209283019291909101906001016127bc565b5050505092915050565b600082601f830112612803578081fd5b81356128116127a7826133f9565b81815291506020808301908481018184028601820187101561283257600080fd5b60005b8481101561285157813584529282019290820190600101612835565b505050505092915050565b600082601f83011261286c578081fd5b813567ffffffffffffffff811115612882578182fd5b6128b360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016133d2565b91508082528360208285010111156128ca57600080fd5b8060208401602084013760009082016020015292915050565b8035600f81900b8114611eae57600080fd5b600060408284031215612906578081fd5b61291060406133d2565b9050813581526020820135602082015292915050565b60006101c0808385031215612939578182fd5b612942816133d2565b91505061294f838361277e565b815261295e836020840161277e565b6020820152612970836040840161277e565b6040820152612982836060840161277e565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff808211156129e457600080fd5b6129f08683870161285c565b83850152610160925082850135915080821115612a0c57600080fd5b612a188683870161285c565b83850152610180925082850135915080821115612a3457600080fd5b612a408683870161285c565b838501526101a0925082850135915080821115612a5c57600080fd5b50612a698582860161285c565b82840152505092915050565b600060208284031215612a86578081fd5b815161198b81613449565b60008060408385031215612aa3578081fd5b8251612aae81613449565b6020939093015192949293505050565b600080600060608486031215612ad2578081fd5b8335612add81613449565b92506020840135612aed81613449565b91506040840135612afd81613449565b809150509250925092565b60008060008060808587031215612b1d578182fd5b8435612b2881613449565b93506020850135612b3881613449565b92506040850135612b4881613449565b9150606085013567ffffffffffffffff811115612b63578182fd5b612b6f878288016127f3565b91505092959194509250565b600080600080600060c08688031215612b92578283fd5b8535612b9d81613449565b94506020860135612bad81613449565b93506040860135612bbd81613449565b9250606086013567ffffffffffffffff811115612bd8578182fd5b612be4888289016127f3565b925050612bf487608088016128f5565b90509295509295909350565b600080600060608486031215612c14578081fd5b8335612c1f81613449565b92506020840135612c2f81613449565b9150604084013567ffffffffffffffff811115612c4a578182fd5b612c56868287016127f3565b9150509250925092565b60008060008060a08587031215612c75578182fd5b8435612c8081613449565b93506020850135612c9081613449565b9250604085013567ffffffffffffffff811115612cab578283fd5b612cb7878288016127f3565b925050612cc786606087016128f5565b905092959194509250565b60008060008060808587031215612ce7578182fd5b8435612cf281613449565b9350612d0186602087016128e3565b9250612b4886604087016128e3565b60008060208385031215612d22578182fd5b823567ffffffffffffffff80821115612d39578384fd5b81850186601f820112612d4a578485fd5b8035925081831115612d5a578485fd5b8660208085028301011115612d6d578485fd5b60200196919550909350505050565b60008060408385031215612d8e578182fd5b823567ffffffffffffffff80821115612da5578384fd5b81850186601f820112612db6578485fd5b80359250612dc66127a7846133f9565b83815260208082019190838101885b87811015612dfe57612dec8c848435890101612926565b85529382019390820190600101612dd5565b50919750880135945050505080821115612e16578283fd5b50612e2385828601612789565b9150509250929050565b60006020808385031215612e3f578182fd5b825167ffffffffffffffff811115612e55578283fd5b80840185601f820112612e66578384fd5b80519150612e766127a7836133f9565b8281528381019082850185850284018601891015612e92578687fd5b8693505b84841015612eb4578051835260019390930192918501918501612e96565b50979650505050505050565b600080600083850360a0811215612ed5578182fd5b6060811215612ee2578182fd5b50612eed60606133d2565b845160078110612efb578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114612afd578182fd5b600060208284031215612f3e578081fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b82811015612f90578151865260209586019590910190600101612f72565b5093949350505050565b60008151808452612fb2816020860160208601613419565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b60008251613006818460208701613419565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526116476080830184612f5f565b600073ffffffffffffffffffffffffffffffffffffffff80861683528085166020840152506060604083015261164a6060830184612f5f565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff94851681529290931660208301526040820152901515606082015260800190565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156131aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613198858351612f9a565b9450928501929085019060010161315e565b5092979650505050505050565b60006020825261198b6020830184612f5f565b60608101600485106131d857fe5b938152602081019290925260409091015290565b60608101600885106131d857fe5b600f93840b81529190920b6020820152604081019190915260600190565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b600060408252613289604083018551612f45565b602084015161329b6060840182612f45565b5060408401516132ae6080840182612f45565b5060608401516132c160a0840182612f45565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c091506101808281870152613332610200870185612f9a565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a08388830301818901526133718287612f9a565b838b015196508489820301868a015261338a8188612f9a565b955050808a0151955050505080858303016101e0860152506133ac8183612f9a565b84810360208601526133be8187612f9a565b979650505050505050565b90815260200190565b60405181810167ffffffffffffffff811182821017156133f157600080fd5b604052919050565b600067ffffffffffffffff82111561340f578081fd5b5060209081020190565b60005b8381101561343457818101518382015260200161341c565b83811115613443576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461346b57600080fd5b5056fea365627a7a723158206f9972d0cf7f4b4b7132e8d5a13de33f086fb9351001e39da804551d1e534d7b6c6578706572696d656e74616cf564736f6c63430005110040" + "object": "0x60806040523480156200001157600080fd5b5060405162003ac838038062003ac883398101604081905262000034916200005a565b600080546001600160a01b0319166001600160a01b03929092169190911790556200008a565b6000602082840312156200006c578081fd5b81516001600160a01b038116811462000083578182fd5b9392505050565b613a2e806200009a6000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806368be3cf2116100b25780639f76ad3511610081578063c7f7142e11610066578063c7f7142e1461024d578063d0eea06d1461026d578063e68248f7146102805761011b565b80639f76ad3514610227578063abffc7611461023a5761011b565b806368be3cf2146101ce5780636dd6b78d146101ee5780638b123a021461020157806398cdafba146102145761011b565b806358306ba0116100ee57806358306ba01461018257806359f515d01461019557806360ee052a146101a857806364ee6ade146101bb5761011b565b80631796fb8714610120578063354152a3146101495780634703a7e61461015c5780634cb8e2531461016f575b600080fd5b61013361012e366004612fd7565b610293565b60405161014091906136d0565b60405180910390f35b610133610157366004612fd7565b610464565b61013361016a366004612f05565b61061e565b61013361017d366004612f05565b6107fa565b610133610190366004612e0d565b610a14565b6101336101a3366004613144565b610aab565b6101336101b6366004612f05565b610b54565b6101336101c9366004612f05565b610e14565b6101e16101dc3660046130d8565b610fda565b6040516101409190613652565b6101336101fc366004612f05565b611119565b61013361020f366004613144565b6113c1565b610133610222366004612e80565b61169a565b610133610235366004612e0d565b6116d6565b610133610248366004613015565b6118da565b61026061025b366004612dc3565b611abd565b6040516101409190613529565b61013361027b366004612f65565b611bf8565b61013361028e366004613015565b611c29565b6060600082519050806040519080825280602002602001820160405280156102c5578160200160208202803883390190505b50915060005b8181101561045a57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff16630e71d1b9905060e01b8a8a8a888151811061032257fe5b602002602001015160405160240161033c93929190613713565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516103c5919061350d565b6000604051808303818686fa925050503d8060008114610401576040519150601f19603f3d011682016040523d82523d6000602084013e610406565b606091505b5090925090506000821561042f57818060200190516104289190810190613446565b9050610437565b50505061045a565b8086858151811061044457fe5b60209081029190910101525050506001016102cb565b5050949350505050565b606060008251905080604051908082528060200260200182016040528015610496578160200160208202803883390190505b50915060005b8181101561045a57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff166307211ef7905060e01b8a8a8a88815181106104f357fe5b602002602001015160405160240161050d93929190613713565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610596919061350d565b6000604051808303818686fa925050503d80600081146105d2576040519150601f19603f3d011682016040523d82523d6000602084013e6105d7565b606091505b5090925090506000821561042f57818060200190516105f99190810190613446565b90508086858151811061060857fe5b602090810291909101015250505060010161049c565b606061062a8385611dff565b8151604080518281526020808402820101909152818015610655578160200160208202803883390190505b50915060005b818110156107f1576000606061066f611e72565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a88815181106106b957fe5b60200260200101516040516024016106d3939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161075c919061350d565b6000604051808303818686fa925050503d8060008114610798576040519150601f19603f3d011682016040523d82523d6000602084013e61079d565b606091505b509092509050600082156107c657818060200190516107bf9190810190613446565b90506107ce565b5050506107f1565b808685815181106107db57fe5b602090810291909101015250505060010161065b565b50509392505050565b60606108068385611dff565b8151604080518281526020808402820101909152818015610831578160200160208202803883390190505b509150600061083e611e8a565b9050600080805b84811015610a08578373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614806108b257508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b1561094a576108d589898984815181106108c857fe5b6020026020010151611ea2565b909350915073ffffffffffffffffffffffffffffffffffffffff82167331e085afd48a1d6e51cc193153d625e8f0514c7f148061093b575073ffffffffffffffffffffffffffffffffffffffff8216731e158c0e93c30d24e918ef83d1e0be23595c3c0f145b1561094557600092505b6109e8565b61095b89858984815181106108c857fe5b909350915082156109e8576000610973858a86611ea2565b909450905073ffffffffffffffffffffffffffffffffffffffff83167331e085afd48a1d6e51cc193153d625e8f0514c7f1480156109dc57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b156109e657600093505b505b828682815181106109f557fe5b6020908102919091010152600101610845565b50505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610a7b57508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610a8557610aa3565b6060610a92868585610e14565b9050610a9f848683610e14565b9150505b949350505050565b6060610ab783836113c1565b905060005b8351811015610b4d57818181518110610ad157fe5b6020026020010151600014610b4557610b2c828281518110610aef57fe5b6020026020010151858381518110610b0357fe5b602002602001015160a00151868481518110610b1b57fe5b602002602001015160800151612216565b828281518110610b3857fe5b6020026020010181815250505b600101610abc565b5092915050565b6060610b608385611dff565b8151604080518281526020808402820101909152818015610b8b578160200160208202803883390190505b5091506000610b98611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610bd857610bd386612258565b610bdb565b60005b90506000610be7611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c2757610c2286612258565b610c2a565b60005b905060005b83811015610e09576001610c41611e8a565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610cd8578651610cb79085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b60200260200101516122f0565b878481518110610cc357fe5b60200260200101819350828152505050610df5565b610ce0611e8a565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610d49578651610cb79084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b8651600090610d829085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610caa57fe5b925090508015610dd857610db7857f2640f62c00000000000000000000000000000000000000000000000000000000836122f0565b888581518110610dc357fe5b60200260200101819450828152505050610df3565b6000878481518110610de657fe5b6020026020010181815250505b505b80610e005750610e09565b50600101610c2f565b505050509392505050565b6060610e208385611dff565b8151604080518281526020808402820101909152818015610e4b578160200160208202803883390190505b50915060005b818110156107f15760006060610e65611e72565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a8881518110610eaf57fe5b6020026020010151604051602401610ec9939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610f52919061350d565b6000604051808303818686fa925050503d8060008114610f8e576040519150601f19603f3d011682016040523d82523d6000602084013e610f93565b606091505b509092509050600082156107c65781806020019051610fb59190810190613446565b905080868581518110610fc457fe5b6020908102919091010152505050600101610e51565b60408051828152602080840282010190915260609082801561101057816020015b6060815260200190600190039081610ffb5790505b50905060005b808314610b4d57600060603086868581811061102e57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13684900301811261106857600080fd5b9091016020810191503567ffffffffffffffff81111561108757600080fd5b3681900382131561109757600080fd5b6040516110a59291906134fd565b600060405180830381855afa9150503d80600081146110e0576040519150601f19603f3d011682016040523d82523d6000602084013e6110e5565b606091505b5091509150816110f757805160208201fd5b8084848151811061110457fe5b60209081029190910101525050600101611016565b60606111258385611dff565b8151604080518281526020808402820101909152818015611150578160200160208202803883390190505b509150600061115d611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461119d5761119886612258565b6111a0565b60005b905060006111ac611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146111ec576111e786612258565b6111ef565b60005b905060005b83811015610e09576001611206611e8a565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561129057865161126f9085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b87848151811061127b57fe5b602002602001018193508281525050506113ad565b611298611e8a565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16141561130157865161126f9084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b865160009061133a9086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610caa57fe5b9250905080156113905761136f847fcd7724c300000000000000000000000000000000000000000000000000000000836122f0565b88858151811061137b57fe5b602002602001018194508281525050506113ab565b600087848151811061139e57fe5b6020026020010181815250505b505b806113b85750610e09565b506001016111f4565b606082516040519080825280602002602001820160405280156113ee578160200160208202803883390190505b506000805491925073ffffffffffffffffffffffffffffffffffffffff909116905b845181146116925783818151811061142457fe5b60200260200101515160001480611452575084818151811061144257fe5b6020026020010151608001516000145b80611474575084818151811061146457fe5b602002602001015160a001516000145b1561149857600083828151811061148757fe5b60200260200101818152505061168a565b600060608373ffffffffffffffffffffffffffffffffffffffff166207a1208573ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b8986815181106114e457fe5b60200260200101518987815181106114f857fe5b602002602001015160405160240161151192919061378e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161159a919061350d565b6000604051808303818686fa925050503d80600081146115d6576040519150601f19603f3d011682016040523d82523d6000602084013e6115db565b606091505b5091509150816116065760008584815181106115f357fe5b602002602001018181525050505061168a565b61160e612bb0565b6000808380602001905161162591908101906133d9565b9194509250905060038351600681111561163b57fe5b141580611646575080155b1561166a57600088878151811061165957fe5b602002602001018181525050611684565b8188878151811061167757fe5b6020026020010181815250505b50505050505b600101611410565b505092915050565b60606116ca858585857f9f76ad35000000000000000000000000000000000000000000000000000000008b612438565b90505b95945050505050565b606060008251905080604051908082528060200260200182016040528015611708578160200160208202803883390190505b5091506000611718878787611abd565b905073ffffffffffffffffffffffffffffffffffffffff811661173d5750610aa39050565b60005b828110156118cf57600060608373ffffffffffffffffffffffffffffffffffffffff1662030d40600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b888151811061179757fe5b60200260200101516040516024016117b1939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161183a919061350d565b6000604051808303818686fa925050503d8060008114611876576040519150601f19603f3d011682016040523d82523d6000602084013e61187b565b606091505b509092509050600082156118a4578180602001905161189d9190810190613446565b90506118ac565b5050506118cf565b808785815181106118b957fe5b6020908102919091010152505050600101611740565b505050949350505050565b60606000825190508060405190808252806020026020018201604052801561190c578160200160208202803883390190505b50915060005b8181101561169257600060606119266125ff565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff1663d06ca61f905060e01b88868151811061196e57fe5b60200260200101518a6040516024016119889291906138eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611a11919061350d565b6000604051808303818686fa925050503d8060008114611a4d576040519150601f19603f3d011682016040523d82523d6000602084013e611a52565b606091505b50909250905060008215611a925781806020019051611a749190810190613346565b600189510381518110611a8357fe5b60200260200101519050611a9a565b505050611692565b80868581518110611aa757fe5b6020908102919091010152505050600101611912565b6040516000906060907f153f59970000000000000000000000000000000000000000000000000000000090611af8908690869060240161354a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff1683604051611b80919061350d565b600060405180830381855afa9150503d8060008114611bbb576040519150601f19603f3d011682016040523d82523d6000602084013e611bc0565b606091505b5091509150818015611bd3575080516020145b15611bed57611be381600c612617565b9350505050611bf1565b5050505b9392505050565b60606116cd858585857f4cb8e253000000000000000000000000000000000000000000000000000000006000612438565b606060008251905080604051908082528060200260200182016040528015611c5b578160200160208202803883390190505b50915060005b818110156116925760006060611c756125ff565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff16631f00ca74905060e01b888681518110611cbd57fe5b60200260200101518a604051602401611cd79291906138eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611d60919061350d565b6000604051808303818686fa925050503d8060008114611d9c576040519150601f19603f3d011682016040523d82523d6000602084013e611da1565b606091505b50909250905060008215611a925781806020019051611dc39190810190613346565b600189510381518110611dd257fe5b6020026020010151905080868581518110611de957fe5b6020908102919091010152505050600101611c61565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611e6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6590613731565b60405180910390fd5b5050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6000806000611eaf611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611ee75785611efd565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611f09611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611f415785611f57565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611f648861265c565b60ff1690506000611f748861265c565b60ff16905060006060611f85612667565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4f61ff8b00000000000000000000000000000000000000000000000000000000179052905173ffffffffffffffffffffffffffffffffffffffff929092169162030d40916120059161350d565b6000604051808303818686fa925050503d8060008114612041576040519150601f19603f3d011682016040523d82523d6000602084013e612046565b606091505b50915091508161206357506000965086955061220e945050505050565b6000818060200190516120799190810190612d7a565b90508073ffffffffffffffffffffffffffffffffffffffff166216e360600073ffffffffffffffffffffffffffffffffffffffff16630c235d96905060e01b89898e60006040516024016120d0949392919061361c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612159919061350d565b6000604051808303818686fa925050503d8060008114612195576040519150601f19603f3d011682016040523d82523d6000602084013e61219a565b606091505b50909350915060008084156121c657838060200190516121bd9190810190612d96565b925090506121dc565b506000995089985061220e975050505050505050565b670de0b6b3a764000087600a0a87600a0a8e850202816121f857fe5b048161220057fe5b049a50985050505050505050505b935093915050565b6000610aa38361224c61223082600163ffffffff61267f16565b612240888763ffffffff61269e16565b9063ffffffff6126cf16565b9063ffffffff6126eb16565b6000612262612715565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b815260040161229a9190613529565b60206040518083038186803b1580156122b257600080fd5b505afa1580156122c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506122ea9190810190612d7a565b92915050565b60008073ffffffffffffffffffffffffffffffffffffffff85166123135761220e565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f0868660405160240161234291906138e2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516123cb919061350d565b6000604051808303818686fa925050503d8060008114612407576040519150601f19603f3d011682016040523d82523d6000602084013e61240c565b606091505b509092509050811561242f578080602001905161242c9190810190613446565b92505b50935093915050565b60606124448688611dff565b845161244f576125f5565b6000806000875160405190808252806020026020018201604052801561247f578160200160208202803883390190505b5093506124a3898b8a60008151811061249457fe5b6020026020010151898961272d565b9250826124b357506125f5915050565b6124c08a8a85898961272d565b9150816124d057506125f5915050565b60005b88518110156125f05760005b88602001518110156125b2576125098a83815181106124fa57fe5b60200260200101518587612216565b945061252089600001516127100161271087612216565b945060006125318d8d888c8c61272d565b90508061253e57506125b2565b8094508a838151811061254d57fe5b602002602001015185106125a95760008b848151811061256957fe5b60200260200101518c858151811061257d57fe5b60200260200101518703612710028161259257fe5b0490508a6000015181116125a75750506125b2565b505b506001016124df565b506125d18982815181106125c257fe5b60200260200101518486612216565b8582815181106125dd57fe5b60209081029190910101526001016124d3565b505050505b9695505050505050565b73f164fc0ec4e93095b804a4795bbe1e041497b92a90565b6000816014018351101561263d5761263d61263860048551856014016129e2565b612a87565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006122ea82612a8f565b73818e6fecd516ecc3849daf6845e3ec868087b75590565b6000828211156126985761269861263860028585612b60565b50900390565b6000826126ad575060006122ea565b828202828482816126ba57fe5b0414611bf157611bf161263860018686612b60565b600082820183811015611bf157611bf161263860008686612b60565b6000816127015761270161263860038585612b60565b600082848161270c57fe5b04949350505050565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b604080516001808252818301909252600091606091829160208083019080388339019050509050858160008151811061276257fe5b60209081029190910101527fffffffff0000000000000000000000000000000000000000000000000000000085167f4cb8e253000000000000000000000000000000000000000000000000000000001415612872576040517f4cb8e25300000000000000000000000000000000000000000000000000000000906127ee908a908a9085906024016135b2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152915061292b565b6040517f9f76ad3500000000000000000000000000000000000000000000000000000000906128ab9086908b908b908690602401613571565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291505b600060603073ffffffffffffffffffffffffffffffffffffffff1684604051612954919061350d565b600060405180830381855afa9150503d806000811461298f576040519150601f19603f3d011682016040523d82523d6000602084013e612994565b606091505b5091509150816129ab5760009450505050506116cd565b808060200190516129bf9190810190613346565b6000815181106129cb57fe5b602002602001015194505050505095945050505050565b6060632800659560e01b848484604051602401612a0193929190613705565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce56700000000000000000000000000000000000000000000000000000000815250604051612af3919061350d565b600060405180830381855afa9150503d8060008114612b2e576040519150601f19603f3d011682016040523d82523d6000602084013e612b33565b606091505b5091509150818015612b46575080516020145b15612b5957612b56816000612b7f565b92505b5050919050565b606063e946c1bb60e01b848484604051602401612a01939291906136e3565b6000611bf1838360008160200183511015612ba757612ba761263860058551856020016129e2565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b80356122ea816139c6565b600082601f830112612bed578081fd5b8135612c00612bfb82613976565b61394f565b8181529150602080830190840160005b83811015612c3d57612c288760208435890101612cb0565b83526020928301929190910190600101612c10565b5050505092915050565b600082601f830112612c57578081fd5b8135612c65612bfb82613976565b818152915060208083019084810181840286018201871015612c8657600080fd5b60005b84811015612ca557813584529282019290820190600101612c89565b505050505092915050565b600082601f830112612cc0578081fd5b813567ffffffffffffffff811115612cd6578182fd5b612d0760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161394f565b9150808252836020828501011115612d1e57600080fd5b8060208401602084013760009082016020015292915050565b8035600f81900b81146122ea57600080fd5b600060408284031215612d5a578081fd5b612d64604061394f565b9050813581526020820135602082015292915050565b600060208284031215612d8b578081fd5b8151611bf1816139c6565b60008060408385031215612da8578081fd5b8251612db3816139c6565b6020939093015192949293505050565b600080600060608486031215612dd7578081fd5b8335612de2816139c6565b92506020840135612df2816139c6565b91506040840135612e02816139c6565b809150509250925092565b60008060008060808587031215612e22578182fd5b8435612e2d816139c6565b93506020850135612e3d816139c6565b92506040850135612e4d816139c6565b9150606085013567ffffffffffffffff811115612e68578182fd5b612e7487828801612c47565b91505092959194509250565b600080600080600060c08688031215612e97578283fd5b8535612ea2816139c6565b94506020860135612eb2816139c6565b93506040860135612ec2816139c6565b9250606086013567ffffffffffffffff811115612edd578182fd5b612ee988828901612c47565b925050612ef98760808801612d49565b90509295509295909350565b600080600060608486031215612f19578081fd5b8335612f24816139c6565b92506020840135612f34816139c6565b9150604084013567ffffffffffffffff811115612f4f578182fd5b612f5b86828701612c47565b9150509250925092565b60008060008060a08587031215612f7a578182fd5b8435612f85816139c6565b93506020850135612f95816139c6565b9250604085013567ffffffffffffffff811115612fb0578283fd5b612fbc87828801612c47565b925050612fcc8660608701612d49565b905092959194509250565b60008060008060808587031215612fec578182fd5b8435612ff7816139c6565b93506130068660208701612d37565b9250612e4d8660408701612d37565b60008060408385031215613027578182fd5b823567ffffffffffffffff8082111561303e578384fd5b81850186601f82011261304f578485fd5b8035925061305f612bfb84613976565b80848252602080830192508084018a82838902870101111561307f578889fd5b8894505b868510156130aa578035613096816139c6565b845260019490940193928101928101613083565b5090965087013593505050808211156130c1578283fd5b506130ce85828601612c47565b9150509250929050565b600080602083850312156130ea578182fd5b823567ffffffffffffffff80821115613101578384fd5b81850186601f820112613112578485fd5b8035925081831115613122578485fd5b8660208085028301011115613135578485fd5b60200196919550909350505050565b60008060408385031215613156578182fd5b67ffffffffffffffff808435111561316c578283fd5b8335840185601f82011261317e578384fd5b803561318c612bfb82613976565b81815260208082019190848101885b8581101561331757813587016101c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f030112156131d9578a8bfd5b6131e46101c061394f565b6131f08e868401612bd2565b81526131ff8e60408401612bd2565b858201526132108e60608401612bd2565b60408201526132228e60808401612bd2565b606082015260a0820135608082015260c082013560a082015260e082013560c082015261010082013560e08201526101208201356101008201526101408201356101208201526101608201358a81111561327a578c8dfd5b6132888f8783860101612cb0565b610140830152506101808201358a8111156132a1578c8dfd5b6132af8f8783860101612cb0565b610160830152506101a08201358a8111156132c8578c8dfd5b6132d68f8783860101612cb0565b610180830152506101c08201358a8111156132ef578c8dfd5b6132fd8f8783860101612cb0565b6101a083015250865250938201939082019060010161319b565b5091975088013593505050508181111561332f578283fd5b61333b86828701612bdd565b925050509250929050565b60006020808385031215613358578182fd5b825167ffffffffffffffff81111561336e578283fd5b80840185601f82011261337f578384fd5b8051915061338f612bfb83613976565b82815283810190828501858502840186018910156133ab578687fd5b8693505b848410156133cd5780518352600193909301929185019185016133af565b50979650505050505050565b600080600083850360a08112156133ee578182fd5b60608112156133fb578182fd5b50613406606061394f565b845160078110613414578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114612e02578182fd5b600060208284031215613457578081fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b828110156134a957815186526020958601959091019060010161348b565b5093949350505050565b600081518084526134cb816020860160208601613996565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b6000825161351f818460208701613996565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526116ca6080830184613478565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526116cd6060830184613478565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff94851681529290931660208301526040820152901515606082015260800190565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156136c3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526136b18583516134b3565b94509285019290850190600101613677565b5092979650505050505050565b600060208252611bf16020830184613478565b60608101600485106136f157fe5b938152602081019290925260409091015290565b60608101600885106136f157fe5b600f93840b81529190920b6020820152604081019190915260600190565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b6000604082526137a260408301855161345e565b60208401516137b4606084018261345e565b5060408401516137c7608084018261345e565b5060608401516137da60a084018261345e565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c09150610180828187015261384b6102008701856134b3565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a083888303018189015261388a82876134b3565b838b015196508489820301868a01526138a381886134b3565b955050808a0151955050505080858303016101e0860152506138c581836134b3565b84810360208601526138d781876134b3565b979650505050505050565b90815260200190565b60006040820184835260406020840152808451808352606085019150602086019250835b8181101561394357835173ffffffffffffffffffffffffffffffffffffffff1683526020938401939092019160010161390f565b50909695505050505050565b60405181810167ffffffffffffffff8111828210171561396e57600080fd5b604052919050565b600067ffffffffffffffff82111561398c578081fd5b5060209081020190565b60005b838110156139b1578181015183820152602001613999565b838111156139c0576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff811681146139e857600080fd5b5056fea365627a7a72315820d5a9bdc2a02db71e54295d8ab576d62ab872477c4a720123d70f8c4c178587fc6c6578706572696d656e74616cf564736f6c63430005110040" }, "deployedBytecode": { - "object": "0x608060405234801561001057600080fd5b50600436106100f55760003560e01c806364ee6ade1161009757806398cdafba1161006657806398cdafba146101ee5780639f76ad3514610201578063c7f7142e14610214578063d0eea06d14610234576100f5565b806364ee6ade1461019557806368be3cf2146101a85780636dd6b78d146101c85780638b123a02146101db576100f5565b80634cb8e253116100d35780634cb8e2531461014957806358306ba01461015c57806359f515d01461016f57806360ee052a14610182576100f5565b80631796fb87146100fa578063354152a3146101235780634703a7e614610136575b600080fd5b61010d610108366004612cd2565b610247565b60405161011a91906131b7565b60405180910390f35b61010d610131366004612cd2565b610418565b61010d610144366004612c00565b6105d2565b61010d610157366004612c00565b6107ae565b61010d61016a366004612b08565b610991565b61010d61017d366004612d7c565b610a28565b61010d610190366004612c00565b610ad1565b61010d6101a3366004612c00565b610d91565b6101bb6101b6366004612d10565b610f57565b60405161011a9190613139565b61010d6101d6366004612c00565b611096565b61010d6101e9366004612d7c565b61133e565b61010d6101fc366004612b7b565b611617565b61010d61020f366004612b08565b611653565b610227610222366004612abe565b611857565b60405161011a9190613010565b61010d610242366004612c60565b611992565b606060008251905080604051908082528060200260200182016040528015610279578160200160208202803883390190505b50915060005b8181101561040e57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff16630e71d1b9905060e01b8a8a8a88815181106102d657fe5b60200260200101516040516024016102f0939291906131fa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516103799190612ff4565b6000604051808303818686fa925050503d80600081146103b5576040519150601f19603f3d011682016040523d82523d6000602084013e6103ba565b606091505b509092509050600082156103e357818060200190516103dc9190810190612f2d565b90506103eb565b50505061040e565b808685815181106103f857fe5b602090810291909101015250505060010161027f565b5050949350505050565b60606000825190508060405190808252806020026020018201604052801561044a578160200160208202803883390190505b50915060005b8181101561040e57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff166307211ef7905060e01b8a8a8a88815181106104a757fe5b60200260200101516040516024016104c1939291906131fa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161054a9190612ff4565b6000604051808303818686fa925050503d8060008114610586576040519150601f19603f3d011682016040523d82523d6000602084013e61058b565b606091505b509092509050600082156103e357818060200190516105ad9190810190612f2d565b9050808685815181106105bc57fe5b6020908102919091010152505050600101610450565b60606105de83856119c3565b8151604080518281526020808402820101909152818015610609578160200160208202803883390190505b50915060005b818110156107a55760006060610623611a36565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a888151811061066d57fe5b6020026020010151604051602401610687939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516107109190612ff4565b6000604051808303818686fa925050503d806000811461074c576040519150601f19603f3d011682016040523d82523d6000602084013e610751565b606091505b5090925090506000821561077a57818060200190516107739190810190612f2d565b9050610782565b5050506107a5565b8086858151811061078f57fe5b602090810291909101015250505060010161060f565b50509392505050565b60606107ba83856119c3565b81516040805182815260208084028201019091528180156107e5578160200160208202803883390190505b50915060006107f2611a4e565b9050600080805b84811015610985578373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16148061086657508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b1561089357610889898989848151811061087c57fe5b6020026020010151611a66565b9093509150610965565b6108a4898589848151811061087c57fe5b909350915082156109655760006108bc858a86611a66565b909450905073ffffffffffffffffffffffffffffffffffffffff83167331e085afd48a1d6e51cc193153d625e8f0514c7f1480610922575073ffffffffffffffffffffffffffffffffffffffff8316731e158c0e93c30d24e918ef83d1e0be23595c3c0f145b801561095957508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b1561096357600093505b505b8286828151811061097257fe5b60209081029190910101526001016107f9565b50505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806109f857508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610a0257610a20565b6060610a0f868585610d91565b9050610a1c848683610d91565b9150505b949350505050565b6060610a34838361133e565b905060005b8351811015610aca57818181518110610a4e57fe5b6020026020010151600014610ac257610aa9828281518110610a6c57fe5b6020026020010151858381518110610a8057fe5b602002602001015160a00151868481518110610a9857fe5b602002602001015160800151611dda565b828281518110610ab557fe5b6020026020010181815250505b600101610a39565b5092915050565b6060610add83856119c3565b8151604080518281526020808402820101909152818015610b08578160200160208202803883390190505b5091506000610b15611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610b5557610b5086611e1c565b610b58565b60005b90506000610b64611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610ba457610b9f86611e1c565b610ba7565b60005b905060005b83811015610d86576001610bbe611a4e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610c55578651610c349085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b6020026020010151611eb4565b878481518110610c4057fe5b60200260200101819350828152505050610d72565b610c5d611a4e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610cc6578651610c349084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b8651600090610cff9085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610c2757fe5b925090508015610d5557610d34857f2640f62c0000000000000000000000000000000000000000000000000000000083611eb4565b888581518110610d4057fe5b60200260200101819450828152505050610d70565b6000878481518110610d6357fe5b6020026020010181815250505b505b80610d7d5750610d86565b50600101610bac565b505050509392505050565b6060610d9d83856119c3565b8151604080518281526020808402820101909152818015610dc8578160200160208202803883390190505b50915060005b818110156107a55760006060610de2611a36565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a8881518110610e2c57fe5b6020026020010151604051602401610e46939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610ecf9190612ff4565b6000604051808303818686fa925050503d8060008114610f0b576040519150601f19603f3d011682016040523d82523d6000602084013e610f10565b606091505b5090925090506000821561077a5781806020019051610f329190810190612f2d565b905080868581518110610f4157fe5b6020908102919091010152505050600101610dce565b604080518281526020808402820101909152606090828015610f8d57816020015b6060815260200190600190039081610f785790505b50905060005b808314610aca576000606030868685818110610fab57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe136849003018112610fe557600080fd5b9091016020810191503567ffffffffffffffff81111561100457600080fd5b3681900382131561101457600080fd5b604051611022929190612fe4565b600060405180830381855afa9150503d806000811461105d576040519150601f19603f3d011682016040523d82523d6000602084013e611062565b606091505b50915091508161107457805160208201fd5b8084848151811061108157fe5b60209081029190910101525050600101610f93565b60606110a283856119c3565b81516040805182815260208084028201019091528180156110cd578160200160208202803883390190505b50915060006110da611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461111a5761111586611e1c565b61111d565b60005b90506000611129611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146111695761116486611e1c565b61116c565b60005b905060005b83811015610d86576001611183611a4e565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561120d5786516111ec9085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b8784815181106111f857fe5b6020026020010181935082815250505061132a565b611215611a4e565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16141561127e5786516111ec9084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610c2757fe5b86516000906112b79086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610c2757fe5b92509050801561130d576112ec847fcd7724c30000000000000000000000000000000000000000000000000000000083611eb4565b8885815181106112f857fe5b60200260200101819450828152505050611328565b600087848151811061131b57fe5b6020026020010181815250505b505b806113355750610d86565b50600101611171565b6060825160405190808252806020026020018201604052801561136b578160200160208202803883390190505b506000805491925073ffffffffffffffffffffffffffffffffffffffff909116905b8451811461160f578381815181106113a157fe5b602002602001015151600014806113cf57508481815181106113bf57fe5b6020026020010151608001516000145b806113f157508481815181106113e157fe5b602002602001015160a001516000145b1561141557600083828151811061140457fe5b602002602001018181525050611607565b600060608373ffffffffffffffffffffffffffffffffffffffff166207a1208573ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b89868151811061146157fe5b602002602001015189878151811061147557fe5b602002602001015160405160240161148e929190613275565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516115179190612ff4565b6000604051808303818686fa925050503d8060008114611553576040519150601f19603f3d011682016040523d82523d6000602084013e611558565b606091505b50915091508161158357600085848151811061157057fe5b6020026020010181815250505050611607565b61158b61275c565b600080838060200190516115a29190810190612ec0565b919450925090506003835160068111156115b857fe5b1415806115c3575080155b156115e75760008887815181106115d657fe5b602002602001018181525050611601565b818887815181106115f457fe5b6020026020010181815250505b50505050505b60010161138d565b505092915050565b6060611647858585857f9f76ad35000000000000000000000000000000000000000000000000000000008b611ffc565b90505b95945050505050565b606060008251905080604051908082528060200260200182016040528015611685578160200160208202803883390190505b5091506000611695878787611857565b905073ffffffffffffffffffffffffffffffffffffffff81166116ba5750610a209050565b60005b8281101561184c57600060608373ffffffffffffffffffffffffffffffffffffffff1662030d40600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b888151811061171457fe5b602002602001015160405160240161172e939291906130d2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516117b79190612ff4565b6000604051808303818686fa925050503d80600081146117f3576040519150601f19603f3d011682016040523d82523d6000602084013e6117f8565b606091505b50909250905060008215611821578180602001905161181a9190810190612f2d565b9050611829565b50505061184c565b8087858151811061183657fe5b60209081029190910101525050506001016116bd565b505050949350505050565b6040516000906060907f153f599700000000000000000000000000000000000000000000000000000000906118929086908690602401613031565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff168360405161191a9190612ff4565b600060405180830381855afa9150503d8060008114611955576040519150601f19603f3d011682016040523d82523d6000602084013e61195a565b606091505b509150915081801561196d575080516020145b156119875761197d81600c6121c3565b935050505061198b565b5050505b9392505050565b606061164a858585857f4cb8e253000000000000000000000000000000000000000000000000000000006000611ffc565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a2990613218565b60405180910390fd5b5050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6000806000611a73611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611aab5785611ac1565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611acd611a4e565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611b055785611b1b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611b2888612208565b60ff1690506000611b3888612208565b60ff16905060006060611b49612213565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4f61ff8b00000000000000000000000000000000000000000000000000000000179052905173ffffffffffffffffffffffffffffffffffffffff929092169162030d4091611bc991612ff4565b6000604051808303818686fa925050503d8060008114611c05576040519150601f19603f3d011682016040523d82523d6000602084013e611c0a565b606091505b509150915081611c27575060009650869550611dd2945050505050565b600081806020019051611c3d9190810190612a75565b90508073ffffffffffffffffffffffffffffffffffffffff166216e360600073ffffffffffffffffffffffffffffffffffffffff16630c235d96905060e01b89898e6000604051602401611c949493929190613103565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611d1d9190612ff4565b6000604051808303818686fa925050503d8060008114611d59576040519150601f19603f3d011682016040523d82523d6000602084013e611d5e565b606091505b5090935091506000808415611d8a5783806020019051611d819190810190612a91565b92509050611da0565b5060009950899850611dd2975050505050505050565b670de0b6b3a764000087600a0a87600a0a8e85020281611dbc57fe5b0481611dc457fe5b049a50985050505050505050505b935093915050565b6000610a2083611e10611df482600163ffffffff61222b16565b611e04888763ffffffff61224a16565b9063ffffffff61227b16565b9063ffffffff61229716565b6000611e266122c1565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b8152600401611e5e9190613010565b60206040518083038186803b158015611e7657600080fd5b505afa158015611e8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611eae9190810190612a75565b92915050565b60008073ffffffffffffffffffffffffffffffffffffffff8516611ed757611dd2565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f08686604051602401611f0691906133c9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611f8f9190612ff4565b6000604051808303818686fa925050503d8060008114611fcb576040519150601f19603f3d011682016040523d82523d6000602084013e611fd0565b606091505b5090925090508115611ff35780806020019051611ff09190810190612f2d565b92505b50935093915050565b606061200886886119c3565b8451612013576121b9565b60008060008751604051908082528060200260200182016040528015612043578160200160208202803883390190505b509350612067898b8a60008151811061205857fe5b602002602001015189896122d9565b92508261207757506121b9915050565b6120848a8a8589896122d9565b91508161209457506121b9915050565b60005b88518110156121b45760005b8860200151811015612176576120cd8a83815181106120be57fe5b60200260200101518587611dda565b94506120e489600001516127100161271087611dda565b945060006120f58d8d888c8c6122d9565b9050806121025750612176565b8094508a838151811061211157fe5b6020026020010151851061216d5760008b848151811061212d57fe5b60200260200101518c858151811061214157fe5b60200260200101518703612710028161215657fe5b0490508a60000151811161216b575050612176565b505b506001016120a3565b5061219589828151811061218657fe5b60200260200101518486611dda565b8582815181106121a157fe5b6020908102919091010152600101612097565b505050505b9695505050505050565b600081601401835110156121e9576121e96121e4600485518560140161258e565b612633565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b6000611eae8261263b565b73818e6fecd516ecc3849daf6845e3ec868087b75590565b600082821115612244576122446121e46002858561270c565b50900390565b60008261225957506000611eae565b8282028284828161226657fe5b041461198b5761198b6121e46001868661270c565b60008282018381101561198b5761198b6121e46000868661270c565b6000816122ad576122ad6121e46003858561270c565b60008284816122b857fe5b04949350505050565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b604080516001808252818301909252600091606091829160208083019080388339019050509050858160008151811061230e57fe5b60209081029190910101527fffffffff0000000000000000000000000000000000000000000000000000000085167f4cb8e25300000000000000000000000000000000000000000000000000000000141561241e576040517f4cb8e253000000000000000000000000000000000000000000000000000000009061239a908a908a908590602401613099565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506124d7565b6040517f9f76ad3500000000000000000000000000000000000000000000000000000000906124579086908b908b908690602401613058565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291505b600060603073ffffffffffffffffffffffffffffffffffffffff16846040516125009190612ff4565b600060405180830381855afa9150503d806000811461253b576040519150601f19603f3d011682016040523d82523d6000602084013e612540565b606091505b50915091508161255757600094505050505061164a565b8080602001905161256b9190810190612e2d565b60008151811061257757fe5b602002602001015194505050505095945050505050565b6060632800659560e01b8484846040516024016125ad939291906131ec565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce5670000000000000000000000000000000000000000000000000000000081525060405161269f9190612ff4565b600060405180830381855afa9150503d80600081146126da576040519150601f19603f3d011682016040523d82523d6000602084013e6126df565b606091505b50915091508180156126f2575080516020145b156127055761270281600061272b565b92505b5050919050565b606063e946c1bb60e01b8484846040516024016125ad939291906131ca565b600061198b838360008160200183511015612753576127536121e4600585518560200161258e565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b8035611eae81613449565b600082601f830112612799578081fd5b81356127ac6127a7826133f9565b6133d2565b8181529150602080830190840160005b838110156127e9576127d4876020843589010161285c565b835260209283019291909101906001016127bc565b5050505092915050565b600082601f830112612803578081fd5b81356128116127a7826133f9565b81815291506020808301908481018184028601820187101561283257600080fd5b60005b8481101561285157813584529282019290820190600101612835565b505050505092915050565b600082601f83011261286c578081fd5b813567ffffffffffffffff811115612882578182fd5b6128b360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016133d2565b91508082528360208285010111156128ca57600080fd5b8060208401602084013760009082016020015292915050565b8035600f81900b8114611eae57600080fd5b600060408284031215612906578081fd5b61291060406133d2565b9050813581526020820135602082015292915050565b60006101c0808385031215612939578182fd5b612942816133d2565b91505061294f838361277e565b815261295e836020840161277e565b6020820152612970836040840161277e565b6040820152612982836060840161277e565b60608201526080820135608082015260a082013560a082015260c082013560c082015260e082013560e08201526101008083013581830152506101208083013581830152506101408083013567ffffffffffffffff808211156129e457600080fd5b6129f08683870161285c565b83850152610160925082850135915080821115612a0c57600080fd5b612a188683870161285c565b83850152610180925082850135915080821115612a3457600080fd5b612a408683870161285c565b838501526101a0925082850135915080821115612a5c57600080fd5b50612a698582860161285c565b82840152505092915050565b600060208284031215612a86578081fd5b815161198b81613449565b60008060408385031215612aa3578081fd5b8251612aae81613449565b6020939093015192949293505050565b600080600060608486031215612ad2578081fd5b8335612add81613449565b92506020840135612aed81613449565b91506040840135612afd81613449565b809150509250925092565b60008060008060808587031215612b1d578182fd5b8435612b2881613449565b93506020850135612b3881613449565b92506040850135612b4881613449565b9150606085013567ffffffffffffffff811115612b63578182fd5b612b6f878288016127f3565b91505092959194509250565b600080600080600060c08688031215612b92578283fd5b8535612b9d81613449565b94506020860135612bad81613449565b93506040860135612bbd81613449565b9250606086013567ffffffffffffffff811115612bd8578182fd5b612be4888289016127f3565b925050612bf487608088016128f5565b90509295509295909350565b600080600060608486031215612c14578081fd5b8335612c1f81613449565b92506020840135612c2f81613449565b9150604084013567ffffffffffffffff811115612c4a578182fd5b612c56868287016127f3565b9150509250925092565b60008060008060a08587031215612c75578182fd5b8435612c8081613449565b93506020850135612c9081613449565b9250604085013567ffffffffffffffff811115612cab578283fd5b612cb7878288016127f3565b925050612cc786606087016128f5565b905092959194509250565b60008060008060808587031215612ce7578182fd5b8435612cf281613449565b9350612d0186602087016128e3565b9250612b4886604087016128e3565b60008060208385031215612d22578182fd5b823567ffffffffffffffff80821115612d39578384fd5b81850186601f820112612d4a578485fd5b8035925081831115612d5a578485fd5b8660208085028301011115612d6d578485fd5b60200196919550909350505050565b60008060408385031215612d8e578182fd5b823567ffffffffffffffff80821115612da5578384fd5b81850186601f820112612db6578485fd5b80359250612dc66127a7846133f9565b83815260208082019190838101885b87811015612dfe57612dec8c848435890101612926565b85529382019390820190600101612dd5565b50919750880135945050505080821115612e16578283fd5b50612e2385828601612789565b9150509250929050565b60006020808385031215612e3f578182fd5b825167ffffffffffffffff811115612e55578283fd5b80840185601f820112612e66578384fd5b80519150612e766127a7836133f9565b8281528381019082850185850284018601891015612e92578687fd5b8693505b84841015612eb4578051835260019390930192918501918501612e96565b50979650505050505050565b600080600083850360a0811215612ed5578182fd5b6060811215612ee2578182fd5b50612eed60606133d2565b845160078110612efb578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114612afd578182fd5b600060208284031215612f3e578081fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b82811015612f90578151865260209586019590910190600101612f72565b5093949350505050565b60008151808452612fb2816020860160208601613419565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b60008251613006818460208701613419565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526116476080830184612f5f565b600073ffffffffffffffffffffffffffffffffffffffff80861683528085166020840152506060604083015261164a6060830184612f5f565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff94851681529290931660208301526040820152901515606082015260800190565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156131aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452613198858351612f9a565b9450928501929085019060010161315e565b5092979650505050505050565b60006020825261198b6020830184612f5f565b60608101600485106131d857fe5b938152602081019290925260409091015290565b60608101600885106131d857fe5b600f93840b81529190920b6020820152604081019190915260600190565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b600060408252613289604083018551612f45565b602084015161329b6060840182612f45565b5060408401516132ae6080840182612f45565b5060608401516132c160a0840182612f45565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c091506101808281870152613332610200870185612f9a565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a08388830301818901526133718287612f9a565b838b015196508489820301868a015261338a8188612f9a565b955050808a0151955050505080858303016101e0860152506133ac8183612f9a565b84810360208601526133be8187612f9a565b979650505050505050565b90815260200190565b60405181810167ffffffffffffffff811182821017156133f157600080fd5b604052919050565b600067ffffffffffffffff82111561340f578081fd5b5060209081020190565b60005b8381101561343457818101518382015260200161341c565b83811115613443576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461346b57600080fd5b5056fea365627a7a723158206f9972d0cf7f4b4b7132e8d5a13de33f086fb9351001e39da804551d1e534d7b6c6578706572696d656e74616cf564736f6c63430005110040" + "object": "0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806368be3cf2116100b25780639f76ad3511610081578063c7f7142e11610066578063c7f7142e1461024d578063d0eea06d1461026d578063e68248f7146102805761011b565b80639f76ad3514610227578063abffc7611461023a5761011b565b806368be3cf2146101ce5780636dd6b78d146101ee5780638b123a021461020157806398cdafba146102145761011b565b806358306ba0116100ee57806358306ba01461018257806359f515d01461019557806360ee052a146101a857806364ee6ade146101bb5761011b565b80631796fb8714610120578063354152a3146101495780634703a7e61461015c5780634cb8e2531461016f575b600080fd5b61013361012e366004612fd7565b610293565b60405161014091906136d0565b60405180910390f35b610133610157366004612fd7565b610464565b61013361016a366004612f05565b61061e565b61013361017d366004612f05565b6107fa565b610133610190366004612e0d565b610a14565b6101336101a3366004613144565b610aab565b6101336101b6366004612f05565b610b54565b6101336101c9366004612f05565b610e14565b6101e16101dc3660046130d8565b610fda565b6040516101409190613652565b6101336101fc366004612f05565b611119565b61013361020f366004613144565b6113c1565b610133610222366004612e80565b61169a565b610133610235366004612e0d565b6116d6565b610133610248366004613015565b6118da565b61026061025b366004612dc3565b611abd565b6040516101409190613529565b61013361027b366004612f65565b611bf8565b61013361028e366004613015565b611c29565b6060600082519050806040519080825280602002602001820160405280156102c5578160200160208202803883390190505b50915060005b8181101561045a57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff16630e71d1b9905060e01b8a8a8a888151811061032257fe5b602002602001015160405160240161033c93929190613713565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516103c5919061350d565b6000604051808303818686fa925050503d8060008114610401576040519150601f19603f3d011682016040523d82523d6000602084013e610406565b606091505b5090925090506000821561042f57818060200190516104289190810190613446565b9050610437565b50505061045a565b8086858151811061044457fe5b60209081029190910101525050506001016102cb565b5050949350505050565b606060008251905080604051908082528060200260200182016040528015610496578160200160208202803883390190505b50915060005b8181101561045a57600060608873ffffffffffffffffffffffffffffffffffffffff16620927c0600073ffffffffffffffffffffffffffffffffffffffff166307211ef7905060e01b8a8a8a88815181106104f357fe5b602002602001015160405160240161050d93929190613713565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610596919061350d565b6000604051808303818686fa925050503d80600081146105d2576040519150601f19603f3d011682016040523d82523d6000602084013e6105d7565b606091505b5090925090506000821561042f57818060200190516105f99190810190613446565b90508086858151811061060857fe5b602090810291909101015250505060010161049c565b606061062a8385611dff565b8151604080518281526020808402820101909152818015610655578160200160208202803883390190505b50915060005b818110156107f1576000606061066f611e72565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663ff1fd974905060e01b8a8a8a88815181106106b957fe5b60200260200101516040516024016106d3939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161075c919061350d565b6000604051808303818686fa925050503d8060008114610798576040519150601f19603f3d011682016040523d82523d6000602084013e61079d565b606091505b509092509050600082156107c657818060200190516107bf9190810190613446565b90506107ce565b5050506107f1565b808685815181106107db57fe5b602090810291909101015250505060010161065b565b50509392505050565b60606108068385611dff565b8151604080518281526020808402820101909152818015610831578160200160208202803883390190505b509150600061083e611e8a565b9050600080805b84811015610a08578373ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614806108b257508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16145b1561094a576108d589898984815181106108c857fe5b6020026020010151611ea2565b909350915073ffffffffffffffffffffffffffffffffffffffff82167331e085afd48a1d6e51cc193153d625e8f0514c7f148061093b575073ffffffffffffffffffffffffffffffffffffffff8216731e158c0e93c30d24e918ef83d1e0be23595c3c0f145b1561094557600092505b6109e8565b61095b89858984815181106108c857fe5b909350915082156109e8576000610973858a86611ea2565b909450905073ffffffffffffffffffffffffffffffffffffffff83167331e085afd48a1d6e51cc193153d625e8f0514c7f1480156109dc57508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16145b156109e657600093505b505b828682815181106109f557fe5b6020908102919091010152600101610845565b50505050509392505050565b60608273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610a7b57508273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16145b15610a8557610aa3565b6060610a92868585610e14565b9050610a9f848683610e14565b9150505b949350505050565b6060610ab783836113c1565b905060005b8351811015610b4d57818181518110610ad157fe5b6020026020010151600014610b4557610b2c828281518110610aef57fe5b6020026020010151858381518110610b0357fe5b602002602001015160a00151868481518110610b1b57fe5b602002602001015160800151612216565b828281518110610b3857fe5b6020026020010181815250505b600101610abc565b5092915050565b6060610b608385611dff565b8151604080518281526020808402820101909152818015610b8b578160200160208202803883390190505b5091506000610b98611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610bd857610bd386612258565b610bdb565b60005b90506000610be7611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614610c2757610c2286612258565b610c2a565b60005b905060005b83811015610e09576001610c41611e8a565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415610cd8578651610cb79085907f2640f62c00000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b60200260200101516122f0565b878481518110610cc357fe5b60200260200101819350828152505050610df5565b610ce0611e8a565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415610d49578651610cb79084907f59e9486200000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b8651600090610d829085907f59e9486200000000000000000000000000000000000000000000000000000000908b9087908110610caa57fe5b925090508015610dd857610db7857f2640f62c00000000000000000000000000000000000000000000000000000000836122f0565b888581518110610dc357fe5b60200260200101819450828152505050610df3565b6000878481518110610de657fe5b6020026020010181815250505b505b80610e005750610e09565b50600101610c2f565b505050509392505050565b6060610e208385611dff565b8151604080518281526020808402820101909152818015610e4b578160200160208202803883390190505b50915060005b818110156107f15760006060610e65611e72565b73ffffffffffffffffffffffffffffffffffffffff16620f4240600073ffffffffffffffffffffffffffffffffffffffff1663144a2752905060e01b898b8a8881518110610eaf57fe5b6020026020010151604051602401610ec9939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051610f52919061350d565b6000604051808303818686fa925050503d8060008114610f8e576040519150601f19603f3d011682016040523d82523d6000602084013e610f93565b606091505b509092509050600082156107c65781806020019051610fb59190810190613446565b905080868581518110610fc457fe5b6020908102919091010152505050600101610e51565b60408051828152602080840282010190915260609082801561101057816020015b6060815260200190600190039081610ffb5790505b50905060005b808314610b4d57600060603086868581811061102e57fe5b6020028201905080357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe13684900301811261106857600080fd5b9091016020810191503567ffffffffffffffff81111561108757600080fd5b3681900382131561109757600080fd5b6040516110a59291906134fd565b600060405180830381855afa9150503d80600081146110e0576040519150601f19603f3d011682016040523d82523d6000602084013e6110e5565b606091505b5091509150816110f757805160208201fd5b8084848151811061110457fe5b60209081029190910101525050600101611016565b60606111258385611dff565b8151604080518281526020808402820101909152818015611150578160200160208202803883390190505b509150600061115d611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161461119d5761119886612258565b6111a0565b60005b905060006111ac611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146111ec576111e786612258565b6111ef565b60005b905060005b83811015610e09576001611206611e8a565b73ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561129057865161126f9085907f95b68fe700000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b87848151811061127b57fe5b602002602001018193508281525050506113ad565b611298611e8a565b73ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff16141561130157865161126f9084907fcd7724c300000000000000000000000000000000000000000000000000000000908a9086908110610caa57fe5b865160009061133a9086907f95b68fe700000000000000000000000000000000000000000000000000000000908b9087908110610caa57fe5b9250905080156113905761136f847fcd7724c300000000000000000000000000000000000000000000000000000000836122f0565b88858151811061137b57fe5b602002602001018194508281525050506113ab565b600087848151811061139e57fe5b6020026020010181815250505b505b806113b85750610e09565b506001016111f4565b606082516040519080825280602002602001820160405280156113ee578160200160208202803883390190505b506000805491925073ffffffffffffffffffffffffffffffffffffffff909116905b845181146116925783818151811061142457fe5b60200260200101515160001480611452575084818151811061144257fe5b6020026020010151608001516000145b80611474575084818151811061146457fe5b602002602001015160a001516000145b1561149857600083828151811061148757fe5b60200260200101818152505061168a565b600060608373ffffffffffffffffffffffffffffffffffffffff166207a1208573ffffffffffffffffffffffffffffffffffffffff1663e77286eb905060e01b8986815181106114e457fe5b60200260200101518987815181106114f857fe5b602002602001015160405160240161151192919061378e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161159a919061350d565b6000604051808303818686fa925050503d80600081146115d6576040519150601f19603f3d011682016040523d82523d6000602084013e6115db565b606091505b5091509150816116065760008584815181106115f357fe5b602002602001018181525050505061168a565b61160e612bb0565b6000808380602001905161162591908101906133d9565b9194509250905060038351600681111561163b57fe5b141580611646575080155b1561166a57600088878151811061165957fe5b602002602001018181525050611684565b8188878151811061167757fe5b6020026020010181815250505b50505050505b600101611410565b505092915050565b60606116ca858585857f9f76ad35000000000000000000000000000000000000000000000000000000008b612438565b90505b95945050505050565b606060008251905080604051908082528060200260200182016040528015611708578160200160208202803883390190505b5091506000611718878787611abd565b905073ffffffffffffffffffffffffffffffffffffffff811661173d5750610aa39050565b60005b828110156118cf57600060608373ffffffffffffffffffffffffffffffffffffffff1662030d40600073ffffffffffffffffffffffffffffffffffffffff1663343fbcdd905060e01b8b8b8b888151811061179757fe5b60200260200101516040516024016117b1939291906135eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161183a919061350d565b6000604051808303818686fa925050503d8060008114611876576040519150601f19603f3d011682016040523d82523d6000602084013e61187b565b606091505b509092509050600082156118a4578180602001905161189d9190810190613446565b90506118ac565b5050506118cf565b808785815181106118b957fe5b6020908102919091010152505050600101611740565b505050949350505050565b60606000825190508060405190808252806020026020018201604052801561190c578160200160208202803883390190505b50915060005b8181101561169257600060606119266125ff565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff1663d06ca61f905060e01b88868151811061196e57fe5b60200260200101518a6040516024016119889291906138eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611a11919061350d565b6000604051808303818686fa925050503d8060008114611a4d576040519150601f19603f3d011682016040523d82523d6000602084013e611a52565b606091505b50909250905060008215611a925781806020019051611a749190810190613346565b600189510381518110611a8357fe5b60200260200101519050611a9a565b505050611692565b80868581518110611aa757fe5b6020908102919091010152505050600101611912565b6040516000906060907f153f59970000000000000000000000000000000000000000000000000000000090611af8908690869060240161354a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060608673ffffffffffffffffffffffffffffffffffffffff1683604051611b80919061350d565b600060405180830381855afa9150503d8060008114611bbb576040519150601f19603f3d011682016040523d82523d6000602084013e611bc0565b606091505b5091509150818015611bd3575080516020145b15611bed57611be381600c612617565b9350505050611bf1565b5050505b9392505050565b60606116cd858585857f4cb8e253000000000000000000000000000000000000000000000000000000006000612438565b606060008251905080604051908082528060200260200182016040528015611c5b578160200160208202803883390190505b50915060005b818110156116925760006060611c756125ff565b73ffffffffffffffffffffffffffffffffffffffff16620249f0600073ffffffffffffffffffffffffffffffffffffffff16631f00ca74905060e01b888681518110611cbd57fe5b60200260200101518a604051602401611cd79291906138eb565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051611d60919061350d565b6000604051808303818686fa925050503d8060008114611d9c576040519150601f19603f3d011682016040523d82523d6000602084013e611da1565b606091505b50909250905060008215611a925781806020019051611dc39190810190613346565b600189510381518110611dd257fe5b6020026020010151905080868581518110611de957fe5b6020908102919091010152505050600101611c61565b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611e6e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6590613731565b60405180910390fd5b5050565b73794e6e91555438afc3ccf1c5076a74f42133d08d90565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc290565b6000806000611eaf611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611ee75785611efd565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611f09611e8a565b73ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614611f415785611f57565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b90506000611f648861265c565b60ff1690506000611f748861265c565b60ff16905060006060611f85612667565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f4f61ff8b00000000000000000000000000000000000000000000000000000000179052905173ffffffffffffffffffffffffffffffffffffffff929092169162030d40916120059161350d565b6000604051808303818686fa925050503d8060008114612041576040519150601f19603f3d011682016040523d82523d6000602084013e612046565b606091505b50915091508161206357506000965086955061220e945050505050565b6000818060200190516120799190810190612d7a565b90508073ffffffffffffffffffffffffffffffffffffffff166216e360600073ffffffffffffffffffffffffffffffffffffffff16630c235d96905060e01b89898e60006040516024016120d0949392919061361c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612159919061350d565b6000604051808303818686fa925050503d8060008114612195576040519150601f19603f3d011682016040523d82523d6000602084013e61219a565b606091505b50909350915060008084156121c657838060200190516121bd9190810190612d96565b925090506121dc565b506000995089985061220e975050505050505050565b670de0b6b3a764000087600a0a87600a0a8e850202816121f857fe5b048161220057fe5b049a50985050505050505050505b935093915050565b6000610aa38361224c61223082600163ffffffff61267f16565b612240888763ffffffff61269e16565b9063ffffffff6126cf16565b9063ffffffff6126eb16565b6000612262612715565b73ffffffffffffffffffffffffffffffffffffffff166306f2bf62836040518263ffffffff1660e01b815260040161229a9190613529565b60206040518083038186803b1580156122b257600080fd5b505afa1580156122c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506122ea9190810190612d7a565b92915050565b60008073ffffffffffffffffffffffffffffffffffffffff85166123135761220e565b60608573ffffffffffffffffffffffffffffffffffffffff16620249f0868660405160240161234291906138e2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290516123cb919061350d565b6000604051808303818686fa925050503d8060008114612407576040519150601f19603f3d011682016040523d82523d6000602084013e61240c565b606091505b509092509050811561242f578080602001905161242c9190810190613446565b92505b50935093915050565b60606124448688611dff565b845161244f576125f5565b6000806000875160405190808252806020026020018201604052801561247f578160200160208202803883390190505b5093506124a3898b8a60008151811061249457fe5b6020026020010151898961272d565b9250826124b357506125f5915050565b6124c08a8a85898961272d565b9150816124d057506125f5915050565b60005b88518110156125f05760005b88602001518110156125b2576125098a83815181106124fa57fe5b60200260200101518587612216565b945061252089600001516127100161271087612216565b945060006125318d8d888c8c61272d565b90508061253e57506125b2565b8094508a838151811061254d57fe5b602002602001015185106125a95760008b848151811061256957fe5b60200260200101518c858151811061257d57fe5b60200260200101518703612710028161259257fe5b0490508a6000015181116125a75750506125b2565b505b506001016124df565b506125d18982815181106125c257fe5b60200260200101518486612216565b8582815181106125dd57fe5b60209081029190910101526001016124d3565b505050505b9695505050505050565b73f164fc0ec4e93095b804a4795bbe1e041497b92a90565b6000816014018351101561263d5761263d61263860048551856014016129e2565b612a87565b50016014015173ffffffffffffffffffffffffffffffffffffffff1690565b60006122ea82612a8f565b73818e6fecd516ecc3849daf6845e3ec868087b75590565b6000828211156126985761269861263860028585612b60565b50900390565b6000826126ad575060006122ea565b828202828482816126ba57fe5b0414611bf157611bf161263860018686612b60565b600082820183811015611bf157611bf161263860008686612b60565b6000816127015761270161263860038585612b60565b600082848161270c57fe5b04949350505050565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9590565b604080516001808252818301909252600091606091829160208083019080388339019050509050858160008151811061276257fe5b60209081029190910101527fffffffff0000000000000000000000000000000000000000000000000000000085167f4cb8e253000000000000000000000000000000000000000000000000000000001415612872576040517f4cb8e25300000000000000000000000000000000000000000000000000000000906127ee908a908a9085906024016135b2565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152915061292b565b6040517f9f76ad3500000000000000000000000000000000000000000000000000000000906128ab9086908b908b908690602401613571565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291505b600060603073ffffffffffffffffffffffffffffffffffffffff1684604051612954919061350d565b600060405180830381855afa9150503d806000811461298f576040519150601f19603f3d011682016040523d82523d6000602084013e612994565b606091505b5091509150816129ab5760009450505050506116cd565b808060200190516129bf9190810190613346565b6000815181106129cb57fe5b602002602001015194505050505095945050505050565b6060632800659560e01b848484604051602401612a0193929190613705565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290509392505050565b805160208201fd5b600060129050600060608373ffffffffffffffffffffffffffffffffffffffff166040518060400160405280600481526020017f313ce56700000000000000000000000000000000000000000000000000000000815250604051612af3919061350d565b600060405180830381855afa9150503d8060008114612b2e576040519150601f19603f3d011682016040523d82523d6000602084013e612b33565b606091505b5091509150818015612b46575080516020145b15612b5957612b56816000612b7f565b92505b5050919050565b606063e946c1bb60e01b848484604051602401612a01939291906136e3565b6000611bf1838360008160200183511015612ba757612ba761263860058551856020016129e2565b50016020015190565b6040805160608101909152806000815260006020820181905260409091015290565b80356122ea816139c6565b600082601f830112612bed578081fd5b8135612c00612bfb82613976565b61394f565b8181529150602080830190840160005b83811015612c3d57612c288760208435890101612cb0565b83526020928301929190910190600101612c10565b5050505092915050565b600082601f830112612c57578081fd5b8135612c65612bfb82613976565b818152915060208083019084810181840286018201871015612c8657600080fd5b60005b84811015612ca557813584529282019290820190600101612c89565b505050505092915050565b600082601f830112612cc0578081fd5b813567ffffffffffffffff811115612cd6578182fd5b612d0760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161394f565b9150808252836020828501011115612d1e57600080fd5b8060208401602084013760009082016020015292915050565b8035600f81900b81146122ea57600080fd5b600060408284031215612d5a578081fd5b612d64604061394f565b9050813581526020820135602082015292915050565b600060208284031215612d8b578081fd5b8151611bf1816139c6565b60008060408385031215612da8578081fd5b8251612db3816139c6565b6020939093015192949293505050565b600080600060608486031215612dd7578081fd5b8335612de2816139c6565b92506020840135612df2816139c6565b91506040840135612e02816139c6565b809150509250925092565b60008060008060808587031215612e22578182fd5b8435612e2d816139c6565b93506020850135612e3d816139c6565b92506040850135612e4d816139c6565b9150606085013567ffffffffffffffff811115612e68578182fd5b612e7487828801612c47565b91505092959194509250565b600080600080600060c08688031215612e97578283fd5b8535612ea2816139c6565b94506020860135612eb2816139c6565b93506040860135612ec2816139c6565b9250606086013567ffffffffffffffff811115612edd578182fd5b612ee988828901612c47565b925050612ef98760808801612d49565b90509295509295909350565b600080600060608486031215612f19578081fd5b8335612f24816139c6565b92506020840135612f34816139c6565b9150604084013567ffffffffffffffff811115612f4f578182fd5b612f5b86828701612c47565b9150509250925092565b60008060008060a08587031215612f7a578182fd5b8435612f85816139c6565b93506020850135612f95816139c6565b9250604085013567ffffffffffffffff811115612fb0578283fd5b612fbc87828801612c47565b925050612fcc8660608701612d49565b905092959194509250565b60008060008060808587031215612fec578182fd5b8435612ff7816139c6565b93506130068660208701612d37565b9250612e4d8660408701612d37565b60008060408385031215613027578182fd5b823567ffffffffffffffff8082111561303e578384fd5b81850186601f82011261304f578485fd5b8035925061305f612bfb84613976565b80848252602080830192508084018a82838902870101111561307f578889fd5b8894505b868510156130aa578035613096816139c6565b845260019490940193928101928101613083565b5090965087013593505050808211156130c1578283fd5b506130ce85828601612c47565b9150509250929050565b600080602083850312156130ea578182fd5b823567ffffffffffffffff80821115613101578384fd5b81850186601f820112613112578485fd5b8035925081831115613122578485fd5b8660208085028301011115613135578485fd5b60200196919550909350505050565b60008060408385031215613156578182fd5b67ffffffffffffffff808435111561316c578283fd5b8335840185601f82011261317e578384fd5b803561318c612bfb82613976565b81815260208082019190848101885b8581101561331757813587016101c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828f030112156131d9578a8bfd5b6131e46101c061394f565b6131f08e868401612bd2565b81526131ff8e60408401612bd2565b858201526132108e60608401612bd2565b60408201526132228e60808401612bd2565b606082015260a0820135608082015260c082013560a082015260e082013560c082015261010082013560e08201526101208201356101008201526101408201356101208201526101608201358a81111561327a578c8dfd5b6132888f8783860101612cb0565b610140830152506101808201358a8111156132a1578c8dfd5b6132af8f8783860101612cb0565b610160830152506101a08201358a8111156132c8578c8dfd5b6132d68f8783860101612cb0565b610180830152506101c08201358a8111156132ef578c8dfd5b6132fd8f8783860101612cb0565b6101a083015250865250938201939082019060010161319b565b5091975088013593505050508181111561332f578283fd5b61333b86828701612bdd565b925050509250929050565b60006020808385031215613358578182fd5b825167ffffffffffffffff81111561336e578283fd5b80840185601f82011261337f578384fd5b8051915061338f612bfb83613976565b82815283810190828501858502840186018910156133ab578687fd5b8693505b848410156133cd5780518352600193909301929185019185016133af565b50979650505050505050565b600080600083850360a08112156133ee578182fd5b60608112156133fb578182fd5b50613406606061394f565b845160078110613414578283fd5b815260208581015190820152604080860151908201526060850151608086015191945092508015158114612e02578182fd5b600060208284031215613457578081fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff169052565b6000815180845260208401935060208301825b828110156134a957815186526020958601959091019060010161348b565b5093949350505050565b600081518084526134cb816020860160208601613996565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b6000825161351f818460208701613996565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152808516604084015250608060608301526116ca6080830184613478565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526116cd6060830184613478565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff94851681529290931660208301526040820152901515606082015260800190565b6000602080830181845280855180835260408601915060408482028701019250838701855b828110156136c3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526136b18583516134b3565b94509285019290850190600101613677565b5092979650505050505050565b600060208252611bf16020830184613478565b60608101600485106136f157fe5b938152602081019290925260409091015290565b60608101600885106136f157fe5b600f93840b81529190920b6020820152604081019190915260600190565b60208082526025908201527f455243323042726964676553616d706c65722f494e56414c49445f544f4b454e60408201527f5f50414952000000000000000000000000000000000000000000000000000000606082015260800190565b6000604082526137a260408301855161345e565b60208401516137b4606084018261345e565b5060408401516137c7608084018261345e565b5060608401516137da60a084018261345e565b50608084015160c083015260a084015160e083015260c0840151610100818185015260e086015191506101208281860152818701519250610140915082828601528087015192505061016082818601528187015192506101c09150610180828187015261384b6102008701856134b3565b8289015194507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc092506101a083888303018189015261388a82876134b3565b838b015196508489820301868a01526138a381886134b3565b955050808a0151955050505080858303016101e0860152506138c581836134b3565b84810360208601526138d781876134b3565b979650505050505050565b90815260200190565b60006040820184835260406020840152808451808352606085019150602086019250835b8181101561394357835173ffffffffffffffffffffffffffffffffffffffff1683526020938401939092019160010161390f565b50909695505050505050565b60405181810167ffffffffffffffff8111828210171561396e57600080fd5b604052919050565b600067ffffffffffffffff82111561398c578081fd5b5060209081020190565b60005b838110156139b1578181015183820152602001613999565b838111156139c0576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff811681146139e857600080fd5b5056fea365627a7a72315820d5a9bdc2a02db71e54295d8ab576d62ab872477c4a720123d70f8c4c178587fc6c6578706572696d656e74616cf564736f6c63430005110040" } } }, diff --git a/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json b/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json index 965a7fd9fd..26a2bf3718 100644 --- a/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json +++ b/packages/contract-artifacts/artifacts/IERC20BridgeSampler.json @@ -178,6 +178,18 @@ "stateMutability": "view", "type": "function" }, + { + "constant": true, + "inputs": [ + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" } + ], + "name": "sampleBuysFromUniswapV2", + "outputs": [{ "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [ @@ -244,6 +256,18 @@ "payable": false, "stateMutability": "view", "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address[]", "name": "path", "type": "address[]" }, + { "internalType": "uint256[]", "name": "takerTokenAmounts", "type": "uint256[]" } + ], + "name": "sampleSellsFromUniswapV2", + "outputs": [{ "internalType": "uint256[]", "name": "makerTokenAmounts", "type": "uint256[]" }], + "payable": false, + "stateMutability": "view", + "type": "function" } ], "devdoc": { @@ -326,6 +350,14 @@ }, "return": "takerTokenAmounts Taker amounts sold at each maker token amount." }, + "sampleBuysFromUniswapV2(address[],uint256[])": { + "details": "Sample buy quotes from UniswapV2.", + "params": { + "makerTokenAmounts": "Maker token buy amount for each sample.", + "path": "Token route." + }, + "return": "takerTokenAmounts Taker amounts sold at each maker token amount." + }, "sampleSellsFromCurve(address,int128,int128,uint256[])": { "details": "Sample sell quotes from Curve.", "params": { @@ -372,6 +404,14 @@ "takerTokenAmounts": "Taker token sell amount for each sample." }, "return": "makerTokenAmounts Maker amounts bought at each taker token amount." + }, + "sampleSellsFromUniswapV2(address[],uint256[])": { + "details": "Sample sell quotes from UniswapV2.", + "params": { + "path": "Token route.", + "takerTokenAmounts": "Taker token sell amount for each sample." + }, + "return": "makerTokenAmounts Maker amounts bought at each taker token amount." } } }, diff --git a/packages/contract-wrappers/CHANGELOG.json b/packages/contract-wrappers/CHANGELOG.json index 8a6bb63677..2b1db67dd6 100644 --- a/packages/contract-wrappers/CHANGELOG.json +++ b/packages/contract-wrappers/CHANGELOG.json @@ -21,6 +21,14 @@ { "note": "Added `ERC20BridgeSampler.sampleBuysFromKyberNetwork`", "pr": 2551 + }, + { + "note": "Added `ERC20BridgeSampler.sampleBuysFromUniswapV2", + "pr": 2595 + }, + { + "note": "Added `ERC20BridgeSampler.sampleSellsFromUniswapV2", + "pr": 2595 } ] }, diff --git a/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts b/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts index 6d452c0899..3f8ee624ef 100644 --- a/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts +++ b/packages/contract-wrappers/src/generated-wrappers/erc20_bridge_sampler.ts @@ -561,6 +561,29 @@ export class ERC20BridgeSamplerContract extends BaseContract { stateMutability: 'view', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'path', + type: 'address[]', + }, + { + name: 'makerTokenAmounts', + type: 'uint256[]', + }, + ], + name: 'sampleBuysFromUniswapV2', + outputs: [ + { + name: 'takerTokenAmounts', + type: 'uint256[]', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, { constant: true, inputs: [ @@ -735,6 +758,29 @@ export class ERC20BridgeSamplerContract extends BaseContract { stateMutability: 'view', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'path', + type: 'address[]', + }, + { + name: 'takerTokenAmounts', + type: 'uint256[]', + }, + ], + name: 'sampleSellsFromUniswapV2', + outputs: [ + { + name: 'makerTokenAmounts', + type: 'uint256[]', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, ] as ContractAbi; return abi; } @@ -1182,6 +1228,34 @@ export class ERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Sample buy quotes from UniswapV2. + * @param path Token route. + * @param makerTokenAmounts Maker token buy amount for each sample. + * @returns takerTokenAmounts Taker amounts sold at each maker token amount. + */ + public sampleBuysFromUniswapV2(path: string[], makerTokenAmounts: BigNumber[]): ContractFunctionObj { + const self = (this as any) as ERC20BridgeSamplerContract; + assert.isArray('path', path); + assert.isArray('makerTokenAmounts', makerTokenAmounts); + const functionSignature = 'sampleBuysFromUniswapV2(address[],uint256[])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [path, makerTokenAmounts]); + }, + }; + } /** * Sample sell quotes from Curve. * @param curveAddress Address of the Curve contract. @@ -1423,6 +1497,34 @@ export class ERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Sample sell quotes from UniswapV2. + * @param path Token route. + * @param takerTokenAmounts Taker token sell amount for each sample. + * @returns makerTokenAmounts Maker amounts bought at each taker token amount. + */ + public sampleSellsFromUniswapV2(path: string[], takerTokenAmounts: BigNumber[]): ContractFunctionObj { + const self = (this as any) as ERC20BridgeSamplerContract; + assert.isArray('path', path); + assert.isArray('takerTokenAmounts', takerTokenAmounts); + const functionSignature = 'sampleSellsFromUniswapV2(address[],uint256[])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [path, takerTokenAmounts]); + }, + }; + } constructor( address: string, 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 ece77afc06..43c258549e 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 @@ -540,6 +540,29 @@ export class IERC20BridgeSamplerContract extends BaseContract { stateMutability: 'view', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'path', + type: 'address[]', + }, + { + name: 'makerTokenAmounts', + type: 'uint256[]', + }, + ], + name: 'sampleBuysFromUniswapV2', + outputs: [ + { + name: 'takerTokenAmounts', + type: 'uint256[]', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, { constant: true, inputs: [ @@ -683,6 +706,29 @@ export class IERC20BridgeSamplerContract extends BaseContract { stateMutability: 'view', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'path', + type: 'address[]', + }, + { + name: 'takerTokenAmounts', + type: 'uint256[]', + }, + ], + name: 'sampleSellsFromUniswapV2', + outputs: [ + { + name: 'makerTokenAmounts', + type: 'uint256[]', + }, + ], + payable: false, + stateMutability: 'view', + type: 'function', + }, ] as ContractAbi; return abi; } @@ -1128,6 +1174,34 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Sample buy quotes from UniswapV2. + * @param path Token route. + * @param makerTokenAmounts Maker token buy amount for each sample. + * @returns takerTokenAmounts Taker amounts sold at each maker token amount. + */ + public sampleBuysFromUniswapV2(path: string[], makerTokenAmounts: BigNumber[]): ContractFunctionObj { + const self = (this as any) as IERC20BridgeSamplerContract; + assert.isArray('path', path); + assert.isArray('makerTokenAmounts', makerTokenAmounts); + const functionSignature = 'sampleBuysFromUniswapV2(address[],uint256[])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [path, makerTokenAmounts]); + }, + }; + } /** * Sample sell quotes from Curve. * @param curveAddress Address of the Curve contract. @@ -1326,6 +1400,34 @@ export class IERC20BridgeSamplerContract extends BaseContract { }, }; } + /** + * Sample sell quotes from UniswapV2. + * @param path Token route. + * @param takerTokenAmounts Taker token sell amount for each sample. + * @returns makerTokenAmounts Maker amounts bought at each taker token amount. + */ + public sampleSellsFromUniswapV2(path: string[], takerTokenAmounts: BigNumber[]): ContractFunctionObj { + const self = (this as any) as IERC20BridgeSamplerContract; + assert.isArray('path', path); + assert.isArray('takerTokenAmounts', takerTokenAmounts); + const functionSignature = 'sampleSellsFromUniswapV2(address[],uint256[])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._performCallAsync( + { ...callData, data: this.getABIEncodedTransactionData() }, + defaultBlock, + ); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + BaseContract._throwIfUnexpectedEmptyCallResult(rawCallResult, abiEncoder); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [path, takerTokenAmounts]); + }, + }; + } constructor( address: string,