diff --git a/contracts/erc20-bridge-sampler/CHANGELOG.json b/contracts/erc20-bridge-sampler/CHANGELOG.json index a1482dcc6d..72ab8c0049 100644 --- a/contracts/erc20-bridge-sampler/CHANGELOG.json +++ b/contracts/erc20-bridge-sampler/CHANGELOG.json @@ -1,4 +1,17 @@ [ + { + "version": "1.1.0", + "changes": [ + { + "note": "Add batch functions to query quotes", + "pr": 2427 + }, + { + "note": "Early exit if a DEX sample fails", + "pr": 2427 + } + ] + }, { "version": "1.0.3", "changes": [ diff --git a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol index 4a420f9295..149c50312b 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/ERC20BridgeSampler.sol @@ -37,9 +37,73 @@ contract ERC20BridgeSampler is DeploymentConstants { bytes4 constant internal ERC20_PROXY_ID = 0xf47261b0; // bytes4(keccak256("ERC20Token(address)")); - uint256 constant internal KYBER_SAMPLE_CALL_GAS = 600e3; + uint256 constant internal KYBER_SAMPLE_CALL_GAS = 1500e3; uint256 constant internal UNISWAP_SAMPLE_CALL_GAS = 150e3; - uint256 constant internal ETH2DAI_SAMPLE_CALL_GAS = 250e3; + uint256 constant internal ETH2DAI_SAMPLE_CALL_GAS = 1000e3; + + /// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param takerTokenAmounts Batches of Taker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Maker amounts bought for each source at + /// each taker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleSells( + LibOrder.Order[][] memory orders, + bytes[][] memory orderSignatures, + address[] memory sources, + uint256[][] memory takerTokenAmounts + ) + public + view + returns ( + OrdersAndSample[] memory ordersAndSamples + ) + { + ordersAndSamples = new OrdersAndSample[](orders.length); + for (uint256 i = 0; i != orders.length; i++) { + ( + uint256[] memory orderFillableAssetAmounts, + uint256[][] memory tokenAmountsBySource + ) = queryOrdersAndSampleSells(orders[i], orderSignatures[i], sources, takerTokenAmounts[i]); + ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts; + ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource; + } + } + + /// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param makerTokenAmounts Batches of Maker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Taker amounts sold for each source at + /// each maker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleBuys( + LibOrder.Order[][] memory orders, + bytes[][] memory orderSignatures, + address[] memory sources, + uint256[][] memory makerTokenAmounts + ) + public + view + returns ( + OrdersAndSample[] memory ordersAndSamples + ) + { + ordersAndSamples = new OrdersAndSample[](orders.length); + for (uint256 i = 0; i != orders.length; i++) { + ( + uint256[] memory orderFillableAssetAmounts, + uint256[][] memory tokenAmountsBySource + ) = queryOrdersAndSampleBuys(orders[i], orderSignatures[i], sources, makerTokenAmounts[i]); + ordersAndSamples[i].orderFillableAssetAmounts = orderFillableAssetAmounts; + ordersAndSamples[i].tokenAmountsBySource = tokenAmountsBySource; + } + } /// @dev Query native orders and sample sell quotes on multiple DEXes at once. /// @param orders Native orders to query. @@ -281,6 +345,8 @@ contract ERC20BridgeSampler is uint256 rate = 0; if (didSucceed) { rate = abi.decode(resultData, (uint256)); + } else { + break; } makerTokenAmounts[i] = rate * @@ -321,6 +387,8 @@ contract ERC20BridgeSampler is uint256 buyAmount = 0; if (didSucceed) { buyAmount = abi.decode(resultData, (uint256)); + } else{ + break; } makerTokenAmounts[i] = buyAmount; } @@ -356,6 +424,8 @@ contract ERC20BridgeSampler is uint256 sellAmount = 0; if (didSucceed) { sellAmount = abi.decode(resultData, (uint256)); + } else { + break; } takerTokenAmounts[i] = sellAmount; } @@ -384,26 +454,28 @@ contract ERC20BridgeSampler is IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWethAddress() ? IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken); for (uint256 i = 0; i < numSamples; i++) { + bool didSucceed = true; if (makerToken == _getWethAddress()) { - makerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(takerTokenExchange), takerTokenExchange.getTokenToEthInputPrice.selector, takerTokenAmounts[i] ); } else if (takerToken == _getWethAddress()) { - makerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(makerTokenExchange), makerTokenExchange.getEthToTokenInputPrice.selector, takerTokenAmounts[i] ); } else { - uint256 ethBought = _callUniswapExchangePriceFunction( + uint256 ethBought; + (ethBought, didSucceed) = _callUniswapExchangePriceFunction( address(takerTokenExchange), takerTokenExchange.getTokenToEthInputPrice.selector, takerTokenAmounts[i] ); if (ethBought != 0) { - makerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (makerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(makerTokenExchange), makerTokenExchange.getEthToTokenInputPrice.selector, ethBought @@ -412,6 +484,9 @@ contract ERC20BridgeSampler is makerTokenAmounts[i] = 0; } } + if (!didSucceed) { + break; + } } } @@ -438,26 +513,28 @@ contract ERC20BridgeSampler is IUniswapExchangeQuotes makerTokenExchange = makerToken == _getWethAddress() ? IUniswapExchangeQuotes(0) : _getUniswapExchange(makerToken); for (uint256 i = 0; i < numSamples; i++) { + bool didSucceed = true; if (makerToken == _getWethAddress()) { - takerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(takerTokenExchange), takerTokenExchange.getTokenToEthOutputPrice.selector, makerTokenAmounts[i] ); } else if (takerToken == _getWethAddress()) { - takerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(makerTokenExchange), makerTokenExchange.getEthToTokenOutputPrice.selector, makerTokenAmounts[i] ); } else { - uint256 ethSold = _callUniswapExchangePriceFunction( + uint256 ethSold; + (ethSold, didSucceed) = _callUniswapExchangePriceFunction( address(makerTokenExchange), makerTokenExchange.getEthToTokenOutputPrice.selector, makerTokenAmounts[i] ); if (ethSold != 0) { - takerTokenAmounts[i] = _callUniswapExchangePriceFunction( + (takerTokenAmounts[i], didSucceed) = _callUniswapExchangePriceFunction( address(takerTokenExchange), takerTokenExchange.getTokenToEthOutputPrice.selector, ethSold @@ -466,6 +543,9 @@ contract ERC20BridgeSampler is takerTokenAmounts[i] = 0; } } + if (!didSucceed) { + break; + } } } @@ -493,12 +573,13 @@ contract ERC20BridgeSampler is ) private view - returns (uint256 outputAmount) + returns (uint256 outputAmount, bool didSucceed) { if (uniswapExchangeAddress == address(0)) { - return 0; + return (outputAmount, didSucceed); } - (bool didSucceed, bytes memory resultData) = + bytes memory resultData; + (didSucceed, resultData) = uniswapExchangeAddress.staticcall.gas(UNISWAP_SAMPLE_CALL_GAS)( abi.encodeWithSelector( functionSelector, diff --git a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol index 9680429d32..42661de16d 100644 --- a/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/src/IERC20BridgeSampler.sol @@ -23,6 +23,52 @@ import "@0x/contracts-exchange-libs/contracts/src/LibOrder.sol"; interface IERC20BridgeSampler { + struct OrdersAndSample { + uint256[] orderFillableAssetAmounts; + uint256[][] tokenAmountsBySource; + } + + /// @dev Query batches of native orders and sample sell quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param takerTokenAmounts Batches of Taker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Maker amounts bought for each source at + /// each taker token amount. First indexed by source index, then sample + /// index. + function queryBatchOrdersAndSampleSells( + LibOrder.Order[][] calldata orders, + bytes[][] calldata orderSignatures, + address[] calldata sources, + uint256[][] calldata takerTokenAmounts + ) + external + view + returns ( + OrdersAndSample[] memory ordersAndSamples + ); + + /// @dev Query batches of native orders and sample buy quotes on multiple DEXes at once. + /// @param orders Batches of Native orders to query. + /// @param orderSignatures Batches of Signatures for each respective order in `orders`. + /// @param sources Address of each DEX. Passing in an unsupported DEX will throw. + /// @param makerTokenAmounts Batches of Maker token sell amount for each sample. + /// @return ordersAndSamples How much taker asset can be filled + /// by each order in `orders`. Taker amounts sold for each source at + /// each maker token amount. First indexed by source index, then sample + /// index + function queryBatchOrdersAndSampleBuys( + LibOrder.Order[][] calldata orders, + bytes[][] calldata orderSignatures, + address[] calldata sources, + uint256[][] calldata makerTokenAmounts + ) + external + view + returns ( + OrdersAndSample[] memory ordersAndSamples + ); /// @dev Query native orders and sample sell quotes on multiple DEXes at once. /// @param orders Native orders to query. diff --git a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol b/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol index 4c98ca2c56..09ad84d197 100644 --- a/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol +++ b/contracts/erc20-bridge-sampler/contracts/test/TestERC20BridgeSampler.sol @@ -338,7 +338,11 @@ contract TestERC20BridgeSampler is bytes32 orderHash = keccak256(abi.encode(order.salt)); // Everything else is derived from the hash. orderInfo.orderHash = orderHash; - orderInfo.orderStatus = LibOrder.OrderStatus(uint256(orderHash) % MAX_ORDER_STATUS); + if (uint256(orderHash) % 100 > 90) { + orderInfo.orderStatus = LibOrder.OrderStatus.FULLY_FILLED; + } else { + orderInfo.orderStatus = LibOrder.OrderStatus.FILLABLE; + } orderInfo.orderTakerAssetFilledAmount = uint256(orderHash) % order.takerAssetAmount; fillableTakerAssetAmount = order.takerAssetAmount - orderInfo.orderTakerAssetFilledAmount; diff --git a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts b/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts index 26c9cae9f9..c134c46d8f 100644 --- a/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts +++ b/contracts/erc20-bridge-sampler/test/erc20-bridge-sampler.ts @@ -195,7 +195,7 @@ blockchainTests('erc20-bridge-sampler', env => { function getDeterministicFillableTakerAssetAmount(order: Order): BigNumber { const hash = getPackedHash(hexUtils.toHex(order.salt, 32)); - const orderStatus = new BigNumber(hash).mod(255).toNumber(); + const orderStatus = new BigNumber(hash).mod(100).toNumber() > 90 ? 5 : 3; const isValidSignature = !!new BigNumber(hash).mod(2).toNumber(); if (orderStatus !== 3 || !isValidSignature) { return constants.ZERO_AMOUNT; @@ -208,7 +208,7 @@ blockchainTests('erc20-bridge-sampler', env => { return order.makerAssetAmount .times(takerAmount) .div(order.takerAssetAmount) - .integerValue(BigNumber.ROUND_DOWN); + .integerValue(BigNumber.ROUND_UP); } function getERC20AssetData(tokenAddress: string): string { @@ -255,7 +255,7 @@ blockchainTests('erc20-bridge-sampler', env => { describe('getOrderFillableTakerAssetAmounts()', () => { it('returns the expected amount for each order', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN); - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const expected = orders.map(getDeterministicFillableTakerAssetAmount); const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq(expected); @@ -269,7 +269,7 @@ blockchainTests('erc20-bridge-sampler', env => { it('returns zero for an order with zero maker asset amount', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); orders[0].makerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); }); @@ -277,7 +277,7 @@ blockchainTests('erc20-bridge-sampler', env => { it('returns zero for an order with zero taker asset amount', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); orders[0].takerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const actual = await testContract.getOrderFillableTakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); }); @@ -293,7 +293,7 @@ blockchainTests('erc20-bridge-sampler', env => { describe('getOrderFillableMakerAssetAmounts()', () => { it('returns the expected amount for each order', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN); - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const expected = orders.map(getDeterministicFillableMakerAssetAmount); const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq(expected); @@ -307,7 +307,7 @@ blockchainTests('erc20-bridge-sampler', env => { it('returns zero for an order with zero maker asset amount', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); orders[0].makerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); }); @@ -315,7 +315,7 @@ blockchainTests('erc20-bridge-sampler', env => { it('returns zero for an order with zero taker asset amount', async () => { const orders = createOrders(MAKER_TOKEN, TAKER_TOKEN, 1); orders[0].takerAssetAmount = constants.ZERO_AMOUNT; - const signatures: string[] = _.times(orders.length, hexUtils.random); + const signatures: string[] = _.times(orders.length, i => hexUtils.random()); const actual = await testContract.getOrderFillableMakerAssetAmounts(orders, signatures).callAsync(); expect(actual).to.deep.eq([constants.ZERO_AMOUNT]); }); @@ -330,7 +330,7 @@ blockchainTests('erc20-bridge-sampler', env => { describe('queryOrdersAndSampleSells()', () => { const ORDERS = createOrders(MAKER_TOKEN, TAKER_TOKEN); - const SIGNATURES: string[] = _.times(ORDERS.length, hexUtils.random); + const SIGNATURES: string[] = _.times(ORDERS.length, i => hexUtils.random()); before(async () => { await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync(); @@ -436,7 +436,7 @@ blockchainTests('erc20-bridge-sampler', env => { describe('queryOrdersAndSampleBuys()', () => { const ORDERS = createOrders(MAKER_TOKEN, TAKER_TOKEN); - const SIGNATURES: string[] = _.times(ORDERS.length, hexUtils.random); + const SIGNATURES: string[] = _.times(ORDERS.length, i => hexUtils.random()); before(async () => { await testContract.createTokenExchanges([MAKER_TOKEN, TAKER_TOKEN]).awaitTransactionSuccessAsync(); diff --git a/packages/abi-gen/src/index.ts b/packages/abi-gen/src/index.ts index 2bef521792..be65fa6475 100644 --- a/packages/abi-gen/src/index.ts +++ b/packages/abi-gen/src/index.ts @@ -277,10 +277,16 @@ for (const abiFileName of abiFileNames) { // use command-line tool black to reformat, if its available try { execSync(`black --line-length 79 ${outFilePath}`); - } catch { - logUtils.warn( - 'Failed to reformat generated Python with black. Do you have it installed? Proceeding anyways...', - ); + } catch (e) { + const BLACK_RC_CANNOT_PARSE = 123; // empirical black exit code + if (e.status === BLACK_RC_CANNOT_PARSE) { + logUtils.warn( + 'Failed to reformat generated Python with black. Exception thrown by execSync("black ...") follows.', + ); + throw e; + } else { + logUtils.warn('Failed to invoke black. Do you have it installed? Proceeding anyways...'); + } } } diff --git a/packages/abi-gen/src/utils.ts b/packages/abi-gen/src/utils.ts index 3327aca139..de82de8b90 100644 --- a/packages/abi-gen/src/utils.ts +++ b/packages/abi-gen/src/utils.ts @@ -195,7 +195,7 @@ export const utils = { return tuple.internalType .replace('struct ', '') .replace('.', '') - .replace('[]', ''); + .replace(/\[\]/g, ''); } else { const tupleComponents = tuple.components; const lengthOfHashSuffix = 8; diff --git a/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json b/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json index a59d9ef4d6..868bef22bb 100644 --- a/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json +++ b/packages/abi-gen/test-cli/fixtures/artifacts/AbiGenDummy.json @@ -193,6 +193,80 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "someBytes", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "anInteger", + "type": "uint32" + }, + { + "internalType": "bytes[]", + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "aString", + "type": "string" + } + ], + "internalType": "struct AbiGenDummy.Struct[][]", + "name": "", + "type": "tuple[][]" + } + ], + "name": "methodAcceptingArrayOfArrayOfStructs", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "components": [ + { + "internalType": "bytes", + "name": "someBytes", + "type": "bytes" + }, + { + "internalType": "uint32", + "name": "anInteger", + "type": "uint32" + }, + { + "internalType": "bytes[]", + "name": "aDynamicArrayOfBytes", + "type": "bytes[]" + }, + { + "internalType": "string", + "name": "aString", + "type": "string" + } + ], + "internalType": "struct AbiGenDummy.Struct[]", + "name": "", + "type": "tuple[]" + } + ], + "name": "methodAcceptingArrayOfStructs", + "outputs": [], + "payable": false, + "stateMutability": "pure", + "type": "function" + }, { "constant": true, "inputs": [], @@ -795,15 +869,15 @@ "evm": { "bytecode": { "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b506114e6806100206000396000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c806376f15d5b11610104578063bb607362116100a2578063d88be12f11610071578063d88be12f1461039b578063ee8b86fb146103a3578063f408fb3114610279578063fa315f9d146103b6576101d9565b8063bb60736214610353578063bdab168814610369578063cd3c0b971461037e578063d6d7618c14610386576101d9565b80638ee52b4e116100de5780638ee52b4e146103225780639a3b618514610335578063a3c2f6b61461033d578063ae2dae1714610345576101d9565b806376f15d5b146102f25780637833bec0146102fa5780637a791e6e1461031a576101d9565b80634303a5421161017c57806359c28add1161014b57806359c28add146102b45780635ba3c7c0146102c957806363d69c88146102d1578063647341eb146102e4576101d9565b80634303a542146102875780634582eab21461028f57806345fdbdb714610297578063586f84b21461029f576101d9565b80632e1a7d4d116101b85780632e1a7d4d146102245780633687617d1461023757806336b32396146102595780633e9ef66a14610279576101d9565b806209e437146101de5780630527c28f146101e85780631310e444146101fb575b600080fd5b6101e66103c4565b005b6101e66101f6366004610c7f565b610401565b61020e610209366004610d87565b610404565b60405161021b91906113e8565b60405180910390f35b6101e6610232366004610d87565b61040b565b61024a610245366004610efc565b61045c565b60405161021b93929190611151565b61026c610267366004610d0b565b6104fc565b60405161021b9190611094565b6101e66101f6366004610d4c565b61020e6105de565b6101e66105e5565b6101e661064a565b6102a761067c565b60405161021b9190611373565b6102bc610684565b60405161021b919061137e565b6101e661068c565b61026c6102df366004610c2e565b6106f1565b6101e66101f6366004610ec9565b61020e6106fa565b61030d610308366004610d9f565b610708565b60405161021b9190611287565b6101e66107c5565b61020e610330366004610d87565b6107ca565b6101e66107d0565b61020e6107db565b6101e66101f6366004610e39565b61035b6107e0565b60405161021b9291906113f1565b610371610819565b60405161021b91906110b5565b6101e661081e565b61038e610855565b60405161021b91906113d5565b61020e6109ae565b6101e66103b1366004610d87565b6101f6565b6101e66101f6366004610d87565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611250565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405161045191906113e8565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161054d929190611072565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105889493929190611133565b6020604051602081039080840390855afa1580156105aa573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611219565b6105e26109b4565b6105e26109cc565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b50929392505050565b600080546001019081905590565b6107106109ec565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b6103ff565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161084b906111ad565b60405180910390a1565b61085d610a1a565b6040805160028082526060828101909352816020015b60608152602001906001900390816108735790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108cd57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061091b57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109c7610a48565b905290565b60405180604001604052806109df610a1a565b8152602001606081525090565b60405180608001604052806109ff610a5b565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610a8c578081fd5b8135610a9f610a9a82611431565b61140a565b8181529150602080830190840160005b83811015610adc57610ac78760208435890101610ae6565b83526020928301929190910190600101610aaf565b5050505092915050565b600082601f830112610af6578081fd5b813567ffffffffffffffff811115610b0c578182fd5b610b3d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161140a565b9150808252836020828501011115610b5457600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610b7e578081fd5b610b88608061140a565b9050813567ffffffffffffffff80821115610ba257600080fd5b610bae85838601610ae6565b8352610bbd8560208601610c14565b60208401526040840135915080821115610bd657600080fd5b610be285838601610a7c565b60408401526060840135915080821115610bfb57600080fd5b50610c0884828501610ae6565b60608301525092915050565b803563ffffffff81168114610c2857600080fd5b92915050565b600080600080600060a08688031215610c45578081fd5b8535610c5081611481565b945060208601359350604086013592506060860135610c6e81611481565b949793965091946080013592915050565b60006020808385031215610c91578182fd5b823567ffffffffffffffff811115610ca7578283fd5b80840185601f820112610cb8578384fd5b80359150610cc8610a9a83611431565b82815283810190828501865b85811015610cfd57610ceb8a888435880101610ae6565b84529286019290860190600101610cd4565b509098975050505050505050565b60008060008060808587031215610d20578384fd5b84359350602085013560ff81168114610d37578384fd5b93969395505050506040820135916060013590565b600060208284031215610d5d578081fd5b813567ffffffffffffffff811115610d73578182fd5b610d7f84828501610ae6565b949350505050565b600060208284031215610d98578081fd5b5035919050565b600060208284031215610db0578081fd5b813567ffffffffffffffff80821115610dc7578283fd5b81840160608187031215610dd9578384fd5b610de3606061140a565b925080358352602081013582811115610dfa578485fd5b610e0687828401610ae6565b602085015250604081013582811115610e1d578485fd5b610e2987828401610ae6565b6040850152509195945050505050565b600060208284031215610e4a578081fd5b813567ffffffffffffffff80821115610e61578283fd5b81840160408187031215610e73578384fd5b610e7d604061140a565b9250803582811115610e8d578485fd5b610e9987828401610b6d565b845250602081013582811115610ead578485fd5b610eb987828401610ae6565b6020850152509195945050505050565b600060208284031215610eda578081fd5b813567ffffffffffffffff811115610ef0578182fd5b610d7f84828501610b6d565b600080600060608486031215610f10578081fd5b83359250602084013567ffffffffffffffff80821115610f2e578283fd5b610f3a87838801610ae6565b93506040860135915080821115610f4f578283fd5b50610f5c86828701610ae6565b9150509250925092565b60008151808452610f7e816020860160208601611451565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160808452610fc56080850182610f66565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b8285101561104b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868303018452611037828251610f66565b600195909501949387019391508601610ffd565b506060880151955088810360608a01526110658187610f66565b9998505050505050505050565b60008351611084818460208801611451565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611126577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452611114858351610fb0565b945092850192908501906001016110da565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526111646060830186610f66565b82810360208401526111768186610f66565b83810360408501526111888186610f66565b979650505050505050565b6000602082526111a66020830184610f66565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526112b7610100850182610f66565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e08601526112f28183610f66565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160408601526113308383610f66565b604087015193508186820301606087015261134b8185610f66565b92505060608601519250808583030160808601525061136a8183610f66565b95945050505050565b905151815260200190565b60006020825282516040602084015261139a6060840182610fb0565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084820301604085015261136a8183610f66565b6000602082526111a66020830184610fb0565b90815260200190565b600083825260406020830152610d7f6040830184610f66565b60405181810167ffffffffffffffff8111828210171561142957600080fd5b604052919050565b600067ffffffffffffffff821115611447578081fd5b5060209081020190565b60005b8381101561146c578181015183820152602001611454565b8381111561147b576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461040157600080fdfea365627a7a723158204f5b227587475ada330d11bfb46020f41172555bd06234eaaad1a7d10a4c2a396c6578706572696d656e74616cf564736f6c634300050c0040", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x14E6 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x1D9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x76F15D5B GT PUSH2 0x104 JUMPI DUP1 PUSH4 0xBB607362 GT PUSH2 0xA2 JUMPI DUP1 PUSH4 0xD88BE12F GT PUSH2 0x71 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x39B JUMPI DUP1 PUSH4 0xEE8B86FB EQ PUSH2 0x3A3 JUMPI DUP1 PUSH4 0xF408FB31 EQ PUSH2 0x279 JUMPI DUP1 PUSH4 0xFA315F9D EQ PUSH2 0x3B6 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0xBB607362 EQ PUSH2 0x353 JUMPI DUP1 PUSH4 0xBDAB1688 EQ PUSH2 0x369 JUMPI DUP1 PUSH4 0xCD3C0B97 EQ PUSH2 0x37E JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x386 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x8EE52B4E GT PUSH2 0xDE JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x322 JUMPI DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x335 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x345 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x2F2 JUMPI DUP1 PUSH4 0x7833BEC0 EQ PUSH2 0x2FA JUMPI DUP1 PUSH4 0x7A791E6E EQ PUSH2 0x31A JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x4303A542 GT PUSH2 0x17C JUMPI DUP1 PUSH4 0x59C28ADD GT PUSH2 0x14B JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x2B4 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x2C9 JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x2D1 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x2E4 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x4303A542 EQ PUSH2 0x287 JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x297 JUMPI DUP1 PUSH4 0x586F84B2 EQ PUSH2 0x29F JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x2E1A7D4D GT PUSH2 0x1B8 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x224 JUMPI DUP1 PUSH4 0x3687617D EQ PUSH2 0x237 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x259 JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x279 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x1DE JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x1E8 JUMPI DUP1 PUSH4 0x1310E444 EQ PUSH2 0x1FB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1E6 PUSH2 0x3C4 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xC7F JUMP JUMPDEST PUSH2 0x401 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x209 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x404 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x13E8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x1E6 PUSH2 0x232 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x40B JUMP JUMPDEST PUSH2 0x24A PUSH2 0x245 CALLDATASIZE PUSH1 0x4 PUSH2 0xEFC JUMP JUMPDEST PUSH2 0x45C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1151 JUMP JUMPDEST PUSH2 0x26C PUSH2 0x267 CALLDATASIZE PUSH1 0x4 PUSH2 0xD0B JUMP JUMPDEST PUSH2 0x4FC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1094 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xD4C JUMP JUMPDEST PUSH2 0x20E PUSH2 0x5DE JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x5E5 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x64A JUMP JUMPDEST PUSH2 0x2A7 PUSH2 0x67C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1373 JUMP JUMPDEST PUSH2 0x2BC PUSH2 0x684 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x137E JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x68C JUMP JUMPDEST PUSH2 0x26C PUSH2 0x2DF CALLDATASIZE PUSH1 0x4 PUSH2 0xC2E JUMP JUMPDEST PUSH2 0x6F1 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC9 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x6FA JUMP JUMPDEST PUSH2 0x30D PUSH2 0x308 CALLDATASIZE PUSH1 0x4 PUSH2 0xD9F JUMP JUMPDEST PUSH2 0x708 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1287 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x7C5 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x330 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x7CA JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x7D0 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x7DB JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xE39 JUMP JUMPDEST PUSH2 0x35B PUSH2 0x7E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP3 SWAP2 SWAP1 PUSH2 0x13F1 JUMP JUMPDEST PUSH2 0x371 PUSH2 0x819 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x10B5 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x81E JUMP JUMPDEST PUSH2 0x38E PUSH2 0x855 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x13D5 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x9AE JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x3B1 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x1F6 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x3F6 SWAP1 PUSH2 0x1250 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST JUMP JUMPDEST POP JUMP JUMPDEST POP PUSH2 0x7C7 SWAP1 JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x7FCF532C15F0A6DB0BD6D0E038BEA71D30D808C7D98CB3BF7268A95BF5081B65 DUP3 PUSH1 0x40 MLOAD PUSH2 0x451 SWAP2 SWAP1 PUSH2 0x13E8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG2 POP JUMP JUMPDEST POP POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP4 MLOAD DUP1 DUP6 ADD DUP6 MSTORE DUP3 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP4 ADD MSTORE DUP5 MLOAD DUP1 DUP7 ADD SWAP1 SWAP6 MSTORE SWAP2 DUP5 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP5 ADD MSTORE SWAP1 SWAP4 SWAP1 SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x54D SWAP3 SWAP2 SWAP1 PUSH2 0x1072 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x588 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1133 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x5AA JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH2 0x7C7 JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x3F6 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x1193 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x3F6 SWAP1 PUSH2 0x1219 JUMP JUMPDEST PUSH2 0x5E2 PUSH2 0x9B4 JUMP JUMPDEST PUSH2 0x5E2 PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x3F6 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x1193 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH2 0x710 PUSH2 0x9EC JUMP JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE SWAP2 DUP3 MSTORE DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP4 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP1 DUP6 ADD SWAP3 SWAP1 SWAP3 MSTORE DUP3 MLOAD DUP1 DUP5 ADD DUP5 MSTORE DUP2 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP5 ADD MSTORE DUP5 DUP5 ADD MSTORE DUP3 MLOAD DUP1 DUP5 ADD SWAP1 SWAP4 MSTORE DUP3 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP3 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x3FF JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x5 DUP2 MSTORE PUSH32 0x68656C6C6F000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x1 SWAP2 JUMP JUMPDEST PUSH1 0x60 SWAP1 JUMP JUMPDEST PUSH32 0x61A6029A4C7DDEE5824D171331EECBD015D26A271310A223718B837FACB5B771 PUSH1 0x40 MLOAD PUSH2 0x84B SWAP1 PUSH2 0x11AD JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMP JUMPDEST PUSH2 0x85D PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x2 DUP1 DUP3 MSTORE PUSH1 0x60 DUP3 DUP2 ADD SWAP1 SWAP4 MSTORE DUP2 PUSH1 0x20 ADD JUMPDEST PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x873 JUMPI SWAP1 POP POP SWAP1 POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x0 DUP2 MLOAD DUP2 LT PUSH2 0x8CD JUMPI INVALID JUMPDEST PUSH1 0x20 MUL PUSH1 0x20 ADD ADD DUP2 SWAP1 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078333231000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x1 DUP2 MLOAD DUP2 LT PUSH2 0x91B JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 DUP1 MLOAD PUSH1 0xC0 DUP2 ADD DUP3 MSTORE PUSH1 0x5 PUSH1 0x80 DUP3 ADD DUP2 DUP2 MSTORE PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP5 ADD MSTORE DUP3 MSTORE DUP2 DUP5 ADD MSTORE DUP1 DUP3 ADD SWAP4 SWAP1 SWAP4 MSTORE DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x6162630000000000000000000000000000000000000000000000000000000000 SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9C7 PUSH2 0xA48 JUMP JUMPDEST SWAP1 MSTORE SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9DF PUSH2 0xA1A JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9FF PUSH2 0xA5B JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xA8C JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xA9F PUSH2 0xA9A DUP3 PUSH2 0x1431 JUMP JUMPDEST PUSH2 0x140A JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xADC JUMPI PUSH2 0xAC7 DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xAE6 JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xAAF JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xAF6 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB0C JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xB3D PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0x140A JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0xB54 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB7E JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0xB88 PUSH1 0x80 PUSH2 0x140A JUMP JUMPDEST SWAP1 POP DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xBA2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBAE DUP6 DUP4 DUP7 ADD PUSH2 0xAE6 JUMP JUMPDEST DUP4 MSTORE PUSH2 0xBBD DUP6 PUSH1 0x20 DUP7 ADD PUSH2 0xC14 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xBD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBE2 DUP6 DUP4 DUP7 ADD PUSH2 0xA7C JUMP JUMPDEST PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x60 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xC08 DUP5 DUP3 DUP6 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP1 CALLDATALOAD PUSH4 0xFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0xC28 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0xC45 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0xC50 DUP2 PUSH2 0x1481 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0xC6E DUP2 PUSH2 0x1481 JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xC91 JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xCA7 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xCB8 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xCC8 PUSH2 0xA9A DUP4 PUSH2 0x1431 JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xCFD JUMPI PUSH2 0xCEB DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xAE6 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xCD4 JUMP JUMPDEST POP SWAP1 SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xD20 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0xD37 JUMPI DUP4 DUP5 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xD5D JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xD73 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xD7F DUP5 DUP3 DUP6 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xD98 JUMPI DUP1 DUP2 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xDB0 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xDC7 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x60 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xDD9 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xDE3 PUSH1 0x60 PUSH2 0x140A JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP4 MSTORE PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xDFA JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE06 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP PUSH1 0x40 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xE1D JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE29 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE4A JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xE61 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xE73 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xE7D PUSH1 0x40 PUSH2 0x140A JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xE8D JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE99 DUP8 DUP3 DUP5 ADD PUSH2 0xB6D JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xEAD JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xEB9 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEDA JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xEF0 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xD7F DUP5 DUP3 DUP6 ADD PUSH2 0xB6D JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0xF10 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP4 CALLDATALOAD SWAP3 POP PUSH1 0x20 DUP5 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF2E JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0xF3A DUP8 DUP4 DUP9 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xF4F JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0xF5C DUP7 DUP3 DUP8 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0xF7E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1451 JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0xFC5 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD DUP8 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x104B JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x1037 DUP3 DUP3 MLOAD PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0xFFD JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x1065 DUP2 DUP8 PUSH2 0xF66 JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x1084 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0x1451 JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 ADD DUP2 DUP5 MSTORE DUP1 DUP6 MLOAD DUP1 DUP4 MSTORE PUSH1 0x40 DUP7 ADD SWAP2 POP PUSH1 0x40 DUP5 DUP3 MUL DUP8 ADD ADD SWAP3 POP DUP4 DUP8 ADD DUP6 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1126 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP9 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x1114 DUP6 DUP4 MLOAD PUSH2 0xFB0 JUMP JUMPDEST SWAP5 POP SWAP3 DUP6 ADD SWAP3 SWAP1 DUP6 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x10DA JUMP JUMPDEST POP SWAP3 SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 MSTORE PUSH2 0x1164 PUSH1 0x60 DUP4 ADD DUP7 PUSH2 0xF66 JUMP JUMPDEST DUP3 DUP2 SUB PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x1176 DUP2 DUP7 PUSH2 0xF66 JUMP JUMPDEST DUP4 DUP2 SUB PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x1188 DUP2 DUP7 PUSH2 0xF66 JUMP JUMPDEST SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x11A6 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0xF66 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE PUSH1 0x4 SWAP1 DUP3 ADD MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x5 SWAP1 DUP3 ADD MSTORE PUSH32 0x6C6F72656D000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP3 ADD MSTORE PUSH1 0xC0 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x80 PUSH1 0x20 DUP5 ADD MSTORE DUP1 MLOAD PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD MLOAD PUSH1 0x60 PUSH1 0xC0 DUP6 ADD MSTORE PUSH2 0x12B7 PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 DUP6 DUP3 SUB ADD PUSH1 0xE0 DUP7 ADD MSTORE PUSH2 0x12F2 DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST SWAP3 POP POP POP PUSH1 0x20 DUP5 ADD MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP1 DUP6 DUP5 SUB ADD PUSH1 0x40 DUP7 ADD MSTORE PUSH2 0x1330 DUP4 DUP4 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 DUP8 ADD MLOAD SWAP4 POP DUP2 DUP7 DUP3 SUB ADD PUSH1 0x60 DUP8 ADD MSTORE PUSH2 0x134B DUP2 DUP6 PUSH2 0xF66 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP7 ADD MLOAD SWAP3 POP DUP1 DUP6 DUP4 SUB ADD PUSH1 0x80 DUP7 ADD MSTORE POP PUSH2 0x136A DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST SWAP1 MLOAD MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x139A PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0xFB0 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x136A DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x11A6 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0xFB0 JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP4 DUP3 MSTORE PUSH1 0x40 PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xD7F PUSH1 0x40 DUP4 ADD DUP5 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1429 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1447 JUMPI DUP1 DUP2 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x146C JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1454 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x147B JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x401 JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723158 KECCAK256 0x4f JUMPDEST 0x22 PUSH22 0x87475ADA330D11BFB46020F41172555BD06234EAAAD1 0xa7 0xd1 EXP 0x4c 0x2a CODECOPY PUSH13 0x6578706572696D656E74616CF5 PUSH5 0x736F6C6343 STOP SDIV 0xc STOP BLOCKHASH ", - "sourceMap": "641:6754:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:6754:0;;;;;;;" + "object": "0x608060405234801561001057600080fd5b50611624806100206000396000f3fe608060405234801561001057600080fd5b50600436106101ef5760003560e01c806377ec31ae1161010f578063bdab1688116100a2578063e796ee9611610071578063e796ee96146103c7578063ee8b86fb146103d5578063f408fb311461028f578063fa315f9d146103e8576101ef565b8063bdab16881461038d578063cd3c0b97146103a2578063d6d7618c146103aa578063d88be12f146103bf576101ef565b80639a3b6185116100de5780639a3b618514610359578063a3c2f6b614610361578063ae2dae1714610369578063bb60736214610377576101ef565b806377ec31ae146103105780637833bec01461031e5780637a791e6e1461033e5780638ee52b4e14610346576101ef565b80634582eab2116101875780635ba3c7c0116101565780635ba3c7c0146102df57806363d69c88146102e7578063647341eb146102fa57806376f15d5b14610308576101ef565b80634582eab2146102a557806345fdbdb7146102ad578063586f84b2146102b557806359c28add146102ca576101ef565b80633687617d116101c35780633687617d1461024d57806336b323961461026f5780633e9ef66a1461028f5780634303a5421461029d576101ef565b806209e437146101f45780630527c28f146101fe5780631310e444146102115780632e1a7d4d1461023a575b600080fd5b6101fc6103f6565b005b6101fc61020c366004610d98565b610433565b61022461021f366004610ec5565b610436565b6040516102319190611526565b60405180910390f35b6101fc610248366004610ec5565b61043d565b61026061025b36600461103a565b61048e565b6040516102319392919061128f565b61028261027d366004610e51565b61052e565b60405161023191906111d2565b6101fc61020c366004610e92565b610224610610565b6101fc610617565b6101fc61067c565b6102bd6106ae565b60405161023191906114b1565b6102d26106b6565b60405161023191906114bc565b6101fc6106be565b6102826102f5366004610cbb565b610723565b6101fc61020c366004611007565b61022461072c565b6101fc61020c366004610e16565b61033161032c366004610edd565b61073a565b60405161023191906113c5565b6101fc6107f7565b610224610354366004610ec5565b6107fc565b6101fc610802565b61022461080d565b6101fc61020c366004610f77565b61037f610812565b60405161023192919061152f565b61039561084b565b60405161023191906111f3565b6101fc610850565b6103b2610887565b6040516102319190611513565b6102246109e0565b6101fc61020c366004610d0c565b6101fc6103e3366004610ec5565b61020c565b6101fc61020c366004610ec5565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104289061138e565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040516104839190611526565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161057f9291906111b0565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105ba9493929190611271565b6020604051602081039080840390855afa1580156105dc573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042890611357565b6106146109e6565b6106146109fe565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b50929392505050565b600080546001019081905590565b610742610a1e565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b610431565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161087d906112eb565b60405180910390a1565b61088f610a4c565b6040805160028082526060828101909352816020015b60608152602001906001900390816108a55790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108ff57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061094d57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109f9610a7a565b905290565b6040518060400160405280610a11610a4c565b8152602001606081525090565b6040518060800160405280610a31610a8d565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610abe578081fd5b8135610ad1610acc8261156f565b611548565b8181529150602080830190840160005b83811015610b0e57610af98760208435890101610b73565b83526020928301929190910190600101610ae1565b5050505092915050565b600082601f830112610b28578081fd5b8135610b36610acc8261156f565b8181529150602080830190840160005b83811015610b0e57610b5e8760208435890101610bfa565b83526020928301929190910190600101610b46565b600082601f830112610b83578081fd5b813567ffffffffffffffff811115610b99578182fd5b610bca60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611548565b9150808252836020828501011115610be157600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610c0b578081fd5b610c156080611548565b9050813567ffffffffffffffff80821115610c2f57600080fd5b610c3b85838601610b73565b8352610c4a8560208601610ca1565b60208401526040840135915080821115610c6357600080fd5b610c6f85838601610aae565b60408401526060840135915080821115610c8857600080fd5b50610c9584828501610b73565b60608301525092915050565b803563ffffffff81168114610cb557600080fd5b92915050565b600080600080600060a08688031215610cd2578081fd5b8535610cdd816115bf565b945060208601359350604086013592506060860135610cfb816115bf565b949793965091946080013592915050565b60006020808385031215610d1e578182fd5b823567ffffffffffffffff811115610d34578283fd5b80840185601f820112610d45578384fd5b80359150610d55610acc8361156f565b82815283810190828501865b85811015610d8a57610d788a888435880101610b18565b84529286019290860190600101610d61565b509098975050505050505050565b60006020808385031215610daa578182fd5b823567ffffffffffffffff811115610dc0578283fd5b80840185601f820112610dd1578384fd5b80359150610de1610acc8361156f565b82815283810190828501865b85811015610d8a57610e048a888435880101610b73565b84529286019290860190600101610ded565b600060208284031215610e27578081fd5b813567ffffffffffffffff811115610e3d578182fd5b610e4984828501610b18565b949350505050565b60008060008060808587031215610e66578182fd5b84359350602085013560ff81168114610e7d578283fd5b93969395505050506040820135916060013590565b600060208284031215610ea3578081fd5b813567ffffffffffffffff811115610eb9578182fd5b610e4984828501610b73565b600060208284031215610ed6578081fd5b5035919050565b600060208284031215610eee578081fd5b813567ffffffffffffffff80821115610f05578283fd5b81840160608187031215610f17578384fd5b610f216060611548565b925080358352602081013582811115610f38578485fd5b610f4487828401610b73565b602085015250604081013582811115610f5b578485fd5b610f6787828401610b73565b6040850152509195945050505050565b600060208284031215610f88578081fd5b813567ffffffffffffffff80821115610f9f578283fd5b81840160408187031215610fb1578384fd5b610fbb6040611548565b9250803582811115610fcb578485fd5b610fd787828401610bfa565b845250602081013582811115610feb578485fd5b610ff787828401610b73565b6020850152509195945050505050565b600060208284031215611018578081fd5b813567ffffffffffffffff81111561102e578182fd5b610e4984828501610bfa565b60008060006060848603121561104e578081fd5b83359250602084013567ffffffffffffffff8082111561106c578283fd5b61107887838801610b73565b9350604086013591508082111561108d578283fd5b5061109a86828701610b73565b9150509250925092565b600081518084526110bc81602086016020860161158f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081516080845261110360808501826110a4565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b82851015611189577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08683030184526111758282516110a4565b60019590950194938701939150860161113b565b506060880151955088810360608a01526111a381876110a4565b9998505050505050505050565b600083516111c281846020880161158f565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611264577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526112528583516110ee565b94509285019290850190600101611218565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526112a260608301866110a4565b82810360208401526112b481866110a4565b83810360408501526112c681866110a4565b979650505050505050565b6000602082526112e460208301846110a4565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526113f56101008501826110a4565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e086015261143081836110a4565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085840301604086015261146e83836110a4565b604087015193508186820301606087015261148981856110a4565b9250506060860151925080858303016080860152506114a881836110a4565b95945050505050565b905151815260200190565b6000602082528251604060208401526114d860608401826110ee565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526114a881836110a4565b6000602082526112e460208301846110ee565b90815260200190565b600083825260406020830152610e4960408301846110a4565b60405181810167ffffffffffffffff8111828210171561156757600080fd5b604052919050565b600067ffffffffffffffff821115611585578081fd5b5060209081020190565b60005b838110156115aa578181015183820152602001611592565b838111156115b9576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461043357600080fdfea365627a7a72315820d4953afa8fe277a67a582a705ec911d7c404b5a84176ab0e36aa14da0e5986326c6578706572696d656e74616cf564736f6c63430005100040", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0x1624 DUP1 PUSH2 0x20 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x1EF JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x77EC31AE GT PUSH2 0x10F JUMPI DUP1 PUSH4 0xBDAB1688 GT PUSH2 0xA2 JUMPI DUP1 PUSH4 0xE796EE96 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0xE796EE96 EQ PUSH2 0x3C7 JUMPI DUP1 PUSH4 0xEE8B86FB EQ PUSH2 0x3D5 JUMPI DUP1 PUSH4 0xF408FB31 EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0xFA315F9D EQ PUSH2 0x3E8 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0xBDAB1688 EQ PUSH2 0x38D JUMPI DUP1 PUSH4 0xCD3C0B97 EQ PUSH2 0x3A2 JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x3AA JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x3BF JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x9A3B6185 GT PUSH2 0xDE JUMPI DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x359 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x361 JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x369 JUMPI DUP1 PUSH4 0xBB607362 EQ PUSH2 0x377 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x77EC31AE EQ PUSH2 0x310 JUMPI DUP1 PUSH4 0x7833BEC0 EQ PUSH2 0x31E JUMPI DUP1 PUSH4 0x7A791E6E EQ PUSH2 0x33E JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x346 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 GT PUSH2 0x187 JUMPI DUP1 PUSH4 0x5BA3C7C0 GT PUSH2 0x156 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x2DF JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x2E7 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x2FA JUMPI DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x308 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x2A5 JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x2AD JUMPI DUP1 PUSH4 0x586F84B2 EQ PUSH2 0x2B5 JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x2CA JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x3687617D GT PUSH2 0x1C3 JUMPI DUP1 PUSH4 0x3687617D EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x26F JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0x4303A542 EQ PUSH2 0x29D JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x1FE JUMPI DUP1 PUSH4 0x1310E444 EQ PUSH2 0x211 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x23A JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FC PUSH2 0x3F6 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xD98 JUMP JUMPDEST PUSH2 0x433 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x21F CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x436 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x1526 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x1FC PUSH2 0x248 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x43D JUMP JUMPDEST PUSH2 0x260 PUSH2 0x25B CALLDATASIZE PUSH1 0x4 PUSH2 0x103A JUMP JUMPDEST PUSH2 0x48E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x128F JUMP JUMPDEST PUSH2 0x282 PUSH2 0x27D CALLDATASIZE PUSH1 0x4 PUSH2 0xE51 JUMP JUMPDEST PUSH2 0x52E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x11D2 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xE92 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x610 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x617 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x67C JUMP JUMPDEST PUSH2 0x2BD PUSH2 0x6AE JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x14B1 JUMP JUMPDEST PUSH2 0x2D2 PUSH2 0x6B6 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x14BC JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x6BE JUMP JUMPDEST PUSH2 0x282 PUSH2 0x2F5 CALLDATASIZE PUSH1 0x4 PUSH2 0xCBB JUMP JUMPDEST PUSH2 0x723 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0x1007 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x72C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xE16 JUMP JUMPDEST PUSH2 0x331 PUSH2 0x32C CALLDATASIZE PUSH1 0x4 PUSH2 0xEDD JUMP JUMPDEST PUSH2 0x73A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x13C5 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x7F7 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x354 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x7FC JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x802 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x80D JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xF77 JUMP JUMPDEST PUSH2 0x37F PUSH2 0x812 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP3 SWAP2 SWAP1 PUSH2 0x152F JUMP JUMPDEST PUSH2 0x395 PUSH2 0x84B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x11F3 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x850 JUMP JUMPDEST PUSH2 0x3B2 PUSH2 0x887 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x1513 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x9E0 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xD0C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x3E3 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x20C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x428 SWAP1 PUSH2 0x138E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST JUMP JUMPDEST POP JUMP JUMPDEST POP PUSH2 0x7C7 SWAP1 JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x7FCF532C15F0A6DB0BD6D0E038BEA71D30D808C7D98CB3BF7268A95BF5081B65 DUP3 PUSH1 0x40 MLOAD PUSH2 0x483 SWAP2 SWAP1 PUSH2 0x1526 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG2 POP JUMP JUMPDEST POP POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP4 MLOAD DUP1 DUP6 ADD DUP6 MSTORE DUP3 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP4 ADD MSTORE DUP5 MLOAD DUP1 DUP7 ADD SWAP1 SWAP6 MSTORE SWAP2 DUP5 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP5 ADD MSTORE SWAP1 SWAP4 SWAP1 SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x57F SWAP3 SWAP2 SWAP1 PUSH2 0x11B0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x5BA SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1271 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x5DC JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH2 0x7C7 JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x428 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x12D1 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x428 SWAP1 PUSH2 0x1357 JUMP JUMPDEST PUSH2 0x614 PUSH2 0x9E6 JUMP JUMPDEST PUSH2 0x614 PUSH2 0x9FE JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x428 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x12D1 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH2 0x742 PUSH2 0xA1E JUMP JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE SWAP2 DUP3 MSTORE DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP4 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP1 DUP6 ADD SWAP3 SWAP1 SWAP3 MSTORE DUP3 MLOAD DUP1 DUP5 ADD DUP5 MSTORE DUP2 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP5 ADD MSTORE DUP5 DUP5 ADD MSTORE DUP3 MLOAD DUP1 DUP5 ADD SWAP1 SWAP4 MSTORE DUP3 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP3 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x431 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x5 DUP2 MSTORE PUSH32 0x68656C6C6F000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x1 SWAP2 JUMP JUMPDEST PUSH1 0x60 SWAP1 JUMP JUMPDEST PUSH32 0x61A6029A4C7DDEE5824D171331EECBD015D26A271310A223718B837FACB5B771 PUSH1 0x40 MLOAD PUSH2 0x87D SWAP1 PUSH2 0x12EB JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMP JUMPDEST PUSH2 0x88F PUSH2 0xA4C JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x2 DUP1 DUP3 MSTORE PUSH1 0x60 DUP3 DUP2 ADD SWAP1 SWAP4 MSTORE DUP2 PUSH1 0x20 ADD JUMPDEST PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x8A5 JUMPI SWAP1 POP POP SWAP1 POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x0 DUP2 MLOAD DUP2 LT PUSH2 0x8FF JUMPI INVALID JUMPDEST PUSH1 0x20 MUL PUSH1 0x20 ADD ADD DUP2 SWAP1 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078333231000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x1 DUP2 MLOAD DUP2 LT PUSH2 0x94D JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 DUP1 MLOAD PUSH1 0xC0 DUP2 ADD DUP3 MSTORE PUSH1 0x5 PUSH1 0x80 DUP3 ADD DUP2 DUP2 MSTORE PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP5 ADD MSTORE DUP3 MSTORE DUP2 DUP5 ADD MSTORE DUP1 DUP3 ADD SWAP4 SWAP1 SWAP4 MSTORE DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x6162630000000000000000000000000000000000000000000000000000000000 SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9F9 PUSH2 0xA7A JUMP JUMPDEST SWAP1 MSTORE SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0xA11 PUSH2 0xA4C JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0xA31 PUSH2 0xA8D JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xABE JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xAD1 PUSH2 0xACC DUP3 PUSH2 0x156F JUMP JUMPDEST PUSH2 0x1548 JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB0E JUMPI PUSH2 0xAF9 DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xB73 JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xAE1 JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xB28 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xB36 PUSH2 0xACC DUP3 PUSH2 0x156F JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB0E JUMPI PUSH2 0xB5E DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xBFA JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xB46 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xB83 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB99 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xBCA PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0x1548 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0xBE1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xC0B JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0xC15 PUSH1 0x80 PUSH2 0x1548 JUMP JUMPDEST SWAP1 POP DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xC2F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC3B DUP6 DUP4 DUP7 ADD PUSH2 0xB73 JUMP JUMPDEST DUP4 MSTORE PUSH2 0xC4A DUP6 PUSH1 0x20 DUP7 ADD PUSH2 0xCA1 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xC63 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC6F DUP6 DUP4 DUP7 ADD PUSH2 0xAAE JUMP JUMPDEST PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x60 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xC88 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xC95 DUP5 DUP3 DUP6 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP1 CALLDATALOAD PUSH4 0xFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0xCB5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0xCD2 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0xCDD DUP2 PUSH2 0x15BF JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0xCFB DUP2 PUSH2 0x15BF JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xD1E JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xD34 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xD45 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xD55 PUSH2 0xACC DUP4 PUSH2 0x156F JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xD8A JUMPI PUSH2 0xD78 DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xB18 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD61 JUMP JUMPDEST POP SWAP1 SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xDAA JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xDC0 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xDD1 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xDE1 PUSH2 0xACC DUP4 PUSH2 0x156F JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xD8A JUMPI PUSH2 0xE04 DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xB73 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xDED JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE27 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xE3D JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xB18 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xE66 JUMPI DUP2 DUP3 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0xE7D JUMPI DUP3 DUP4 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEA3 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xEB9 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xED6 JUMPI DUP1 DUP2 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEEE JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF05 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x60 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xF17 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xF21 PUSH1 0x60 PUSH2 0x1548 JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP4 MSTORE PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xF38 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xF44 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP PUSH1 0x40 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xF5B JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xF67 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xF88 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF9F JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xFB1 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xFBB PUSH1 0x40 PUSH2 0x1548 JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xFCB JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xFD7 DUP8 DUP3 DUP5 ADD PUSH2 0xBFA JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xFEB JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xFF7 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1018 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x102E JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xBFA JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x104E JUMPI DUP1 DUP2 REVERT JUMPDEST DUP4 CALLDATALOAD SWAP3 POP PUSH1 0x20 DUP5 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x106C JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x1078 DUP8 DUP4 DUP9 ADD PUSH2 0xB73 JUMP JUMPDEST SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x108D JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0x109A DUP7 DUP3 DUP8 ADD PUSH2 0xB73 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0x10BC DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x158F JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0x1103 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD DUP8 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x1189 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x1175 DUP3 DUP3 MLOAD PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0x113B JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x11A3 DUP2 DUP8 PUSH2 0x10A4 JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x11C2 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0x158F JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 ADD DUP2 DUP5 MSTORE DUP1 DUP6 MLOAD DUP1 DUP4 MSTORE PUSH1 0x40 DUP7 ADD SWAP2 POP PUSH1 0x40 DUP5 DUP3 MUL DUP8 ADD ADD SWAP3 POP DUP4 DUP8 ADD DUP6 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1264 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP9 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x1252 DUP6 DUP4 MLOAD PUSH2 0x10EE JUMP JUMPDEST SWAP5 POP SWAP3 DUP6 ADD SWAP3 SWAP1 DUP6 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x1218 JUMP JUMPDEST POP SWAP3 SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 MSTORE PUSH2 0x12A2 PUSH1 0x60 DUP4 ADD DUP7 PUSH2 0x10A4 JUMP JUMPDEST DUP3 DUP2 SUB PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x12B4 DUP2 DUP7 PUSH2 0x10A4 JUMP JUMPDEST DUP4 DUP2 SUB PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x12C6 DUP2 DUP7 PUSH2 0x10A4 JUMP JUMPDEST SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x12E4 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x10A4 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE PUSH1 0x4 SWAP1 DUP3 ADD MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x5 SWAP1 DUP3 ADD MSTORE PUSH32 0x6C6F72656D000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP3 ADD MSTORE PUSH1 0xC0 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x80 PUSH1 0x20 DUP5 ADD MSTORE DUP1 MLOAD PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD MLOAD PUSH1 0x60 PUSH1 0xC0 DUP6 ADD MSTORE PUSH2 0x13F5 PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 DUP6 DUP3 SUB ADD PUSH1 0xE0 DUP7 ADD MSTORE PUSH2 0x1430 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST SWAP3 POP POP POP PUSH1 0x20 DUP5 ADD MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP1 DUP6 DUP5 SUB ADD PUSH1 0x40 DUP7 ADD MSTORE PUSH2 0x146E DUP4 DUP4 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 DUP8 ADD MLOAD SWAP4 POP DUP2 DUP7 DUP3 SUB ADD PUSH1 0x60 DUP8 ADD MSTORE PUSH2 0x1489 DUP2 DUP6 PUSH2 0x10A4 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP7 ADD MLOAD SWAP3 POP DUP1 DUP6 DUP4 SUB ADD PUSH1 0x80 DUP7 ADD MSTORE POP PUSH2 0x14A8 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST SWAP1 MLOAD MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x14D8 PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0x10EE JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x14A8 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x12E4 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x10EE JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP4 DUP3 MSTORE PUSH1 0x40 PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xE49 PUSH1 0x40 DUP4 ADD DUP5 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1567 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1585 JUMPI DUP1 DUP2 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x15AA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1592 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x15B9 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x433 JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723158 KECCAK256 0xD4 SWAP6 GASPRICE STATICCALL DUP16 0xE2 PUSH24 0xA67A582A705EC911D7C404B5A84176AB0E36AA14DA0E5986 ORIGIN PUSH13 0x6578706572696D656E74616CF5 PUSH5 0x736F6C6343 STOP SDIV LT STOP BLOCKHASH ", + "sourceMap": "641:6913:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:6913:0;;;;;;;" }, "deployedBytecode": { "linkReferences": {}, - "object": "0x608060405234801561001057600080fd5b50600436106101d95760003560e01c806376f15d5b11610104578063bb607362116100a2578063d88be12f11610071578063d88be12f1461039b578063ee8b86fb146103a3578063f408fb3114610279578063fa315f9d146103b6576101d9565b8063bb60736214610353578063bdab168814610369578063cd3c0b971461037e578063d6d7618c14610386576101d9565b80638ee52b4e116100de5780638ee52b4e146103225780639a3b618514610335578063a3c2f6b61461033d578063ae2dae1714610345576101d9565b806376f15d5b146102f25780637833bec0146102fa5780637a791e6e1461031a576101d9565b80634303a5421161017c57806359c28add1161014b57806359c28add146102b45780635ba3c7c0146102c957806363d69c88146102d1578063647341eb146102e4576101d9565b80634303a542146102875780634582eab21461028f57806345fdbdb714610297578063586f84b21461029f576101d9565b80632e1a7d4d116101b85780632e1a7d4d146102245780633687617d1461023757806336b32396146102595780633e9ef66a14610279576101d9565b806209e437146101de5780630527c28f146101e85780631310e444146101fb575b600080fd5b6101e66103c4565b005b6101e66101f6366004610c7f565b610401565b61020e610209366004610d87565b610404565b60405161021b91906113e8565b60405180910390f35b6101e6610232366004610d87565b61040b565b61024a610245366004610efc565b61045c565b60405161021b93929190611151565b61026c610267366004610d0b565b6104fc565b60405161021b9190611094565b6101e66101f6366004610d4c565b61020e6105de565b6101e66105e5565b6101e661064a565b6102a761067c565b60405161021b9190611373565b6102bc610684565b60405161021b919061137e565b6101e661068c565b61026c6102df366004610c2e565b6106f1565b6101e66101f6366004610ec9565b61020e6106fa565b61030d610308366004610d9f565b610708565b60405161021b9190611287565b6101e66107c5565b61020e610330366004610d87565b6107ca565b6101e66107d0565b61020e6107db565b6101e66101f6366004610e39565b61035b6107e0565b60405161021b9291906113f1565b610371610819565b60405161021b91906110b5565b6101e661081e565b61038e610855565b60405161021b91906113d5565b61020e6109ae565b6101e66103b1366004610d87565b6101f6565b6101e66101f6366004610d87565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611250565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405161045191906113e8565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161054d929190611072565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105889493929190611133565b6020604051602081039080840390855afa1580156105aa573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611219565b6105e26109b4565b6105e26109cc565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b50929392505050565b600080546001019081905590565b6107106109ec565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b6103ff565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161084b906111ad565b60405180910390a1565b61085d610a1a565b6040805160028082526060828101909352816020015b60608152602001906001900390816108735790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108cd57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061091b57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109c7610a48565b905290565b60405180604001604052806109df610a1a565b8152602001606081525090565b60405180608001604052806109ff610a5b565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610a8c578081fd5b8135610a9f610a9a82611431565b61140a565b8181529150602080830190840160005b83811015610adc57610ac78760208435890101610ae6565b83526020928301929190910190600101610aaf565b5050505092915050565b600082601f830112610af6578081fd5b813567ffffffffffffffff811115610b0c578182fd5b610b3d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161140a565b9150808252836020828501011115610b5457600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610b7e578081fd5b610b88608061140a565b9050813567ffffffffffffffff80821115610ba257600080fd5b610bae85838601610ae6565b8352610bbd8560208601610c14565b60208401526040840135915080821115610bd657600080fd5b610be285838601610a7c565b60408401526060840135915080821115610bfb57600080fd5b50610c0884828501610ae6565b60608301525092915050565b803563ffffffff81168114610c2857600080fd5b92915050565b600080600080600060a08688031215610c45578081fd5b8535610c5081611481565b945060208601359350604086013592506060860135610c6e81611481565b949793965091946080013592915050565b60006020808385031215610c91578182fd5b823567ffffffffffffffff811115610ca7578283fd5b80840185601f820112610cb8578384fd5b80359150610cc8610a9a83611431565b82815283810190828501865b85811015610cfd57610ceb8a888435880101610ae6565b84529286019290860190600101610cd4565b509098975050505050505050565b60008060008060808587031215610d20578384fd5b84359350602085013560ff81168114610d37578384fd5b93969395505050506040820135916060013590565b600060208284031215610d5d578081fd5b813567ffffffffffffffff811115610d73578182fd5b610d7f84828501610ae6565b949350505050565b600060208284031215610d98578081fd5b5035919050565b600060208284031215610db0578081fd5b813567ffffffffffffffff80821115610dc7578283fd5b81840160608187031215610dd9578384fd5b610de3606061140a565b925080358352602081013582811115610dfa578485fd5b610e0687828401610ae6565b602085015250604081013582811115610e1d578485fd5b610e2987828401610ae6565b6040850152509195945050505050565b600060208284031215610e4a578081fd5b813567ffffffffffffffff80821115610e61578283fd5b81840160408187031215610e73578384fd5b610e7d604061140a565b9250803582811115610e8d578485fd5b610e9987828401610b6d565b845250602081013582811115610ead578485fd5b610eb987828401610ae6565b6020850152509195945050505050565b600060208284031215610eda578081fd5b813567ffffffffffffffff811115610ef0578182fd5b610d7f84828501610b6d565b600080600060608486031215610f10578081fd5b83359250602084013567ffffffffffffffff80821115610f2e578283fd5b610f3a87838801610ae6565b93506040860135915080821115610f4f578283fd5b50610f5c86828701610ae6565b9150509250925092565b60008151808452610f7e816020860160208601611451565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160808452610fc56080850182610f66565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b8285101561104b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868303018452611037828251610f66565b600195909501949387019391508601610ffd565b506060880151955088810360608a01526110658187610f66565b9998505050505050505050565b60008351611084818460208801611451565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611126577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452611114858351610fb0565b945092850192908501906001016110da565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526111646060830186610f66565b82810360208401526111768186610f66565b83810360408501526111888186610f66565b979650505050505050565b6000602082526111a66020830184610f66565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526112b7610100850182610f66565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e08601526112f28183610f66565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160408601526113308383610f66565b604087015193508186820301606087015261134b8185610f66565b92505060608601519250808583030160808601525061136a8183610f66565b95945050505050565b905151815260200190565b60006020825282516040602084015261139a6060840182610fb0565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084820301604085015261136a8183610f66565b6000602082526111a66020830184610fb0565b90815260200190565b600083825260406020830152610d7f6040830184610f66565b60405181810167ffffffffffffffff8111828210171561142957600080fd5b604052919050565b600067ffffffffffffffff821115611447578081fd5b5060209081020190565b60005b8381101561146c578181015183820152602001611454565b8381111561147b576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461040157600080fdfea365627a7a723158204f5b227587475ada330d11bfb46020f41172555bd06234eaaad1a7d10a4c2a396c6578706572696d656e74616cf564736f6c634300050c0040", - "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x1D9 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x76F15D5B GT PUSH2 0x104 JUMPI DUP1 PUSH4 0xBB607362 GT PUSH2 0xA2 JUMPI DUP1 PUSH4 0xD88BE12F GT PUSH2 0x71 JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x39B JUMPI DUP1 PUSH4 0xEE8B86FB EQ PUSH2 0x3A3 JUMPI DUP1 PUSH4 0xF408FB31 EQ PUSH2 0x279 JUMPI DUP1 PUSH4 0xFA315F9D EQ PUSH2 0x3B6 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0xBB607362 EQ PUSH2 0x353 JUMPI DUP1 PUSH4 0xBDAB1688 EQ PUSH2 0x369 JUMPI DUP1 PUSH4 0xCD3C0B97 EQ PUSH2 0x37E JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x386 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x8EE52B4E GT PUSH2 0xDE JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x322 JUMPI DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x335 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x33D JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x345 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x2F2 JUMPI DUP1 PUSH4 0x7833BEC0 EQ PUSH2 0x2FA JUMPI DUP1 PUSH4 0x7A791E6E EQ PUSH2 0x31A JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x4303A542 GT PUSH2 0x17C JUMPI DUP1 PUSH4 0x59C28ADD GT PUSH2 0x14B JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x2B4 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x2C9 JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x2D1 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x2E4 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x4303A542 EQ PUSH2 0x287 JUMPI DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x297 JUMPI DUP1 PUSH4 0x586F84B2 EQ PUSH2 0x29F JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH4 0x2E1A7D4D GT PUSH2 0x1B8 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x224 JUMPI DUP1 PUSH4 0x3687617D EQ PUSH2 0x237 JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x259 JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x279 JUMPI PUSH2 0x1D9 JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x1DE JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x1E8 JUMPI DUP1 PUSH4 0x1310E444 EQ PUSH2 0x1FB JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1E6 PUSH2 0x3C4 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xC7F JUMP JUMPDEST PUSH2 0x401 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x209 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x404 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x13E8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x1E6 PUSH2 0x232 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x40B JUMP JUMPDEST PUSH2 0x24A PUSH2 0x245 CALLDATASIZE PUSH1 0x4 PUSH2 0xEFC JUMP JUMPDEST PUSH2 0x45C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1151 JUMP JUMPDEST PUSH2 0x26C PUSH2 0x267 CALLDATASIZE PUSH1 0x4 PUSH2 0xD0B JUMP JUMPDEST PUSH2 0x4FC JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1094 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xD4C JUMP JUMPDEST PUSH2 0x20E PUSH2 0x5DE JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x5E5 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x64A JUMP JUMPDEST PUSH2 0x2A7 PUSH2 0x67C JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1373 JUMP JUMPDEST PUSH2 0x2BC PUSH2 0x684 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x137E JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x68C JUMP JUMPDEST PUSH2 0x26C PUSH2 0x2DF CALLDATASIZE PUSH1 0x4 PUSH2 0xC2E JUMP JUMPDEST PUSH2 0x6F1 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC9 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x6FA JUMP JUMPDEST PUSH2 0x30D PUSH2 0x308 CALLDATASIZE PUSH1 0x4 PUSH2 0xD9F JUMP JUMPDEST PUSH2 0x708 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x1287 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x7C5 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x330 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x7CA JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x7D0 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x7DB JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xE39 JUMP JUMPDEST PUSH2 0x35B PUSH2 0x7E0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP3 SWAP2 SWAP1 PUSH2 0x13F1 JUMP JUMPDEST PUSH2 0x371 PUSH2 0x819 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x10B5 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x81E JUMP JUMPDEST PUSH2 0x38E PUSH2 0x855 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x21B SWAP2 SWAP1 PUSH2 0x13D5 JUMP JUMPDEST PUSH2 0x20E PUSH2 0x9AE JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x3B1 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH2 0x1F6 JUMP JUMPDEST PUSH2 0x1E6 PUSH2 0x1F6 CALLDATASIZE PUSH1 0x4 PUSH2 0xD87 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x3F6 SWAP1 PUSH2 0x1250 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST JUMP JUMPDEST POP JUMP JUMPDEST POP PUSH2 0x7C7 SWAP1 JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x7FCF532C15F0A6DB0BD6D0E038BEA71D30D808C7D98CB3BF7268A95BF5081B65 DUP3 PUSH1 0x40 MLOAD PUSH2 0x451 SWAP2 SWAP1 PUSH2 0x13E8 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG2 POP JUMP JUMPDEST POP POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP4 MLOAD DUP1 DUP6 ADD DUP6 MSTORE DUP3 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP4 ADD MSTORE DUP5 MLOAD DUP1 DUP7 ADD SWAP1 SWAP6 MSTORE SWAP2 DUP5 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP5 ADD MSTORE SWAP1 SWAP4 SWAP1 SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x54D SWAP3 SWAP2 SWAP1 PUSH2 0x1072 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x588 SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1133 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x5AA JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH2 0x7C7 JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x3F6 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x1193 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x3F6 SWAP1 PUSH2 0x1219 JUMP JUMPDEST PUSH2 0x5E2 PUSH2 0x9B4 JUMP JUMPDEST PUSH2 0x5E2 PUSH2 0x9CC JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x3F6 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x1193 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH2 0x710 PUSH2 0x9EC JUMP JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE SWAP2 DUP3 MSTORE DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP4 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP1 DUP6 ADD SWAP3 SWAP1 SWAP3 MSTORE DUP3 MLOAD DUP1 DUP5 ADD DUP5 MSTORE DUP2 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP5 ADD MSTORE DUP5 DUP5 ADD MSTORE DUP3 MLOAD DUP1 DUP5 ADD SWAP1 SWAP4 MSTORE DUP3 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP3 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x3FF JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x5 DUP2 MSTORE PUSH32 0x68656C6C6F000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x1 SWAP2 JUMP JUMPDEST PUSH1 0x60 SWAP1 JUMP JUMPDEST PUSH32 0x61A6029A4C7DDEE5824D171331EECBD015D26A271310A223718B837FACB5B771 PUSH1 0x40 MLOAD PUSH2 0x84B SWAP1 PUSH2 0x11AD JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMP JUMPDEST PUSH2 0x85D PUSH2 0xA1A JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x2 DUP1 DUP3 MSTORE PUSH1 0x60 DUP3 DUP2 ADD SWAP1 SWAP4 MSTORE DUP2 PUSH1 0x20 ADD JUMPDEST PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x873 JUMPI SWAP1 POP POP SWAP1 POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x0 DUP2 MLOAD DUP2 LT PUSH2 0x8CD JUMPI INVALID JUMPDEST PUSH1 0x20 MUL PUSH1 0x20 ADD ADD DUP2 SWAP1 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078333231000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x1 DUP2 MLOAD DUP2 LT PUSH2 0x91B JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 DUP1 MLOAD PUSH1 0xC0 DUP2 ADD DUP3 MSTORE PUSH1 0x5 PUSH1 0x80 DUP3 ADD DUP2 DUP2 MSTORE PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP5 ADD MSTORE DUP3 MSTORE DUP2 DUP5 ADD MSTORE DUP1 DUP3 ADD SWAP4 SWAP1 SWAP4 MSTORE DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x6162630000000000000000000000000000000000000000000000000000000000 SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9C7 PUSH2 0xA48 JUMP JUMPDEST SWAP1 MSTORE SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9DF PUSH2 0xA1A JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9FF PUSH2 0xA5B JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xA8C JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xA9F PUSH2 0xA9A DUP3 PUSH2 0x1431 JUMP JUMPDEST PUSH2 0x140A JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xADC JUMPI PUSH2 0xAC7 DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xAE6 JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xAAF JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xAF6 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB0C JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xB3D PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0x140A JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0xB54 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xB7E JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0xB88 PUSH1 0x80 PUSH2 0x140A JUMP JUMPDEST SWAP1 POP DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xBA2 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBAE DUP6 DUP4 DUP7 ADD PUSH2 0xAE6 JUMP JUMPDEST DUP4 MSTORE PUSH2 0xBBD DUP6 PUSH1 0x20 DUP7 ADD PUSH2 0xC14 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xBD6 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xBE2 DUP6 DUP4 DUP7 ADD PUSH2 0xA7C JUMP JUMPDEST PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x60 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xBFB JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xC08 DUP5 DUP3 DUP6 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP1 CALLDATALOAD PUSH4 0xFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0xC28 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0xC45 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0xC50 DUP2 PUSH2 0x1481 JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0xC6E DUP2 PUSH2 0x1481 JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xC91 JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xCA7 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xCB8 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xCC8 PUSH2 0xA9A DUP4 PUSH2 0x1431 JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xCFD JUMPI PUSH2 0xCEB DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xAE6 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xCD4 JUMP JUMPDEST POP SWAP1 SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xD20 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0xD37 JUMPI DUP4 DUP5 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xD5D JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xD73 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xD7F DUP5 DUP3 DUP6 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xD98 JUMPI DUP1 DUP2 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xDB0 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xDC7 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x60 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xDD9 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xDE3 PUSH1 0x60 PUSH2 0x140A JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP4 MSTORE PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xDFA JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE06 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP PUSH1 0x40 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xE1D JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE29 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE4A JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xE61 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xE73 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xE7D PUSH1 0x40 PUSH2 0x140A JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xE8D JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xE99 DUP8 DUP3 DUP5 ADD PUSH2 0xB6D JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xEAD JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xEB9 DUP8 DUP3 DUP5 ADD PUSH2 0xAE6 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEDA JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xEF0 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xD7F DUP5 DUP3 DUP6 ADD PUSH2 0xB6D JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0xF10 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP4 CALLDATALOAD SWAP3 POP PUSH1 0x20 DUP5 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF2E JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0xF3A DUP8 DUP4 DUP9 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xF4F JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0xF5C DUP7 DUP3 DUP8 ADD PUSH2 0xAE6 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0xF7E DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x1451 JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0xFC5 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD DUP8 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x104B JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x1037 DUP3 DUP3 MLOAD PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0xFFD JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x1065 DUP2 DUP8 PUSH2 0xF66 JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x1084 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0x1451 JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 ADD DUP2 DUP5 MSTORE DUP1 DUP6 MLOAD DUP1 DUP4 MSTORE PUSH1 0x40 DUP7 ADD SWAP2 POP PUSH1 0x40 DUP5 DUP3 MUL DUP8 ADD ADD SWAP3 POP DUP4 DUP8 ADD DUP6 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1126 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP9 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x1114 DUP6 DUP4 MLOAD PUSH2 0xFB0 JUMP JUMPDEST SWAP5 POP SWAP3 DUP6 ADD SWAP3 SWAP1 DUP6 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x10DA JUMP JUMPDEST POP SWAP3 SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 MSTORE PUSH2 0x1164 PUSH1 0x60 DUP4 ADD DUP7 PUSH2 0xF66 JUMP JUMPDEST DUP3 DUP2 SUB PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x1176 DUP2 DUP7 PUSH2 0xF66 JUMP JUMPDEST DUP4 DUP2 SUB PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x1188 DUP2 DUP7 PUSH2 0xF66 JUMP JUMPDEST SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x11A6 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0xF66 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE PUSH1 0x4 SWAP1 DUP3 ADD MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x5 SWAP1 DUP3 ADD MSTORE PUSH32 0x6C6F72656D000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP3 ADD MSTORE PUSH1 0xC0 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x80 PUSH1 0x20 DUP5 ADD MSTORE DUP1 MLOAD PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD MLOAD PUSH1 0x60 PUSH1 0xC0 DUP6 ADD MSTORE PUSH2 0x12B7 PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 DUP6 DUP3 SUB ADD PUSH1 0xE0 DUP7 ADD MSTORE PUSH2 0x12F2 DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST SWAP3 POP POP POP PUSH1 0x20 DUP5 ADD MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP1 DUP6 DUP5 SUB ADD PUSH1 0x40 DUP7 ADD MSTORE PUSH2 0x1330 DUP4 DUP4 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 DUP8 ADD MLOAD SWAP4 POP DUP2 DUP7 DUP3 SUB ADD PUSH1 0x60 DUP8 ADD MSTORE PUSH2 0x134B DUP2 DUP6 PUSH2 0xF66 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP7 ADD MLOAD SWAP3 POP DUP1 DUP6 DUP4 SUB ADD PUSH1 0x80 DUP7 ADD MSTORE POP PUSH2 0x136A DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST SWAP1 MLOAD MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x139A PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0xFB0 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x136A DUP2 DUP4 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x11A6 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0xFB0 JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP4 DUP3 MSTORE PUSH1 0x40 PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xD7F PUSH1 0x40 DUP4 ADD DUP5 PUSH2 0xF66 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1429 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1447 JUMPI DUP1 DUP2 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x146C JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1454 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x147B JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x401 JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723158 KECCAK256 0x4f JUMPDEST 0x22 PUSH22 0x87475ADA330D11BFB46020F41172555BD06234EAAAD1 0xa7 0xd1 EXP 0x4c 0x2a CODECOPY PUSH13 0x6578706572696D656E74616CF5 PUSH5 0x736F6C6343 STOP SDIV 0xc STOP BLOCKHASH ", - "sourceMap": "641:6754:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:6754:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1496:107;;;:::i;:::-;;3110:63;;;;;;;;;:::i;6359:128::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;4968:84;;;;;;;;;:::i;6982:345::-;;;;;;;;;:::i;:::-;;;;;;;;;;2288:334;;;;;;;;;:::i;:::-;;;;;;;;2948:52;;;;;;;5964:117;;;:::i;1389:101::-;;;:::i;1286:97::-;;;:::i;4321:153::-;;;:::i;:::-;;;;;;;;4053:73;;;:::i;:::-;;;;;;;;1609:111;;;:::i;2776:166::-;;;;;;;;;:::i;3319:52::-;;;;;;;4500:72;;;:::i;6560:317::-;;;;;;;;;:::i;:::-;;;;;;;;5773:112;;;:::i;989:140::-;;;;;;;;;:::i;4577:69::-;;;:::i;862:121::-;;;:::i;3984:64::-;;;;;;;4652:134;;;:::i;:::-;;;;;;;;;3809:80;;;:::i;:::-;;;;;;;;5118:125;;;:::i;3453:350::-;;;:::i;:::-;;;;;;;;1135:145;;;:::i;6160:123::-;;;;;;;;;:::i;4792:47::-;;;;;;;1496:107;1564:32;;;;;;;;;;;;;;;;;;;;1496:107::o;3110:63::-;;:::o;6359:128::-;-1:-1:-1;6476:4:0;;6359:128::o;4968:84::-;5029:10;5018:27;;;5041:3;5018:27;;;;;;;;;;;;;;;4968:84;:::o;6982:345::-;-1:-1:-1;;7229:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;6982:345:0:o;2288:334::-;2399:21;2436:19;:56;;;;;;;;;;;;;;;;;;;2502:20;2552:6;2560:4;2535:30;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2535:30:0;;;2525:41;;;;;;2502:64;;2583:32;2593:12;2607:1;2610;2613;2583:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;2583:32:0;;;;;;2288:334;-1:-1:-1;;;;;;;;2288:334:0:o;5964:117::-;6070:4;5964:117;;:::o;1389:101::-;1469:13;;;;;;;;;;;;;;;;1462:21;;;;;;;1469:13;1462:21;;;;1286:97;1353:23;;;;;;;;;;;4321:153;4415:51;;:::i;4053:73::-;4103:19;;:::i;1609:111::-;1698:14;;;;;;;;;;;;;;;;1683:30;;;;;;;1698:14;1683:30;;;;2776:166;-1:-1:-1;2934:1:0;;2776:166;-1:-1:-1;;;2776:166:0:o;4500:72::-;4540:4;4555:14;;4568:1;4555:14;;;;;4500:72;:::o;6560:317::-;6674:20;;:::i;:::-;-1:-1:-1;6717:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6560:317::o;5773:112::-;5857:21;;989:140;1117:1;:5;;989:140::o;4577:69::-;4629:9;:14;;4642:1;4629:14;;;4577:69::o;862:121::-;975:1;862:121;:::o;4652:134::-;4760:19;;;;;;;;;;;;;;;;;4768:1;4652:134;:::o;3809:80::-;3870:15;3809:80;:::o;5118:125::-;5167:69;;;;;;;;;;;;;;;5118:125::o;3453:350::-;3497:15;;:::i;:::-;3551:14;;;3563:1;3551:14;;;3524:24;3551:14;;;;;;;;;;;;;;;;;;;;;;;;;;3524:41;;3575:22;;;;;;;;;;;;;;;;;:9;3585:1;3575:12;;;;;;;;;;;;;:22;;;;3607;;;;;;;;;;;;;;;;;:9;3617:1;3607:12;;;;;;;;;;;;;;;;;;:22;;;;3647:149;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3647:149:0;;;;-1:-1:-1;3453:350:0;:::o;1135:145::-;711:4;1135:145;:::o;641:6754::-;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;158:685:-1:-;;276:3;269:4;261:6;257:17;253:27;243:2;;-1:-1;;284:12;243:2;331:6;318:20;353:81;368:65;426:6;368:65;;;353:81;;;462:21;;;344:90;-1:-1;506:4;519:14;;;;494:17;;614:1;599:238;624:6;621:1;618:13;599:238;;;731:42;769:3;506:4;707:3;694:17;498:6;682:30;;731:42;;;719:55;;506:4;788:14;;;;816;;;;;646:1;639:9;599:238;;;603:14;;;;236:607;;;;;1706:432;;1803:3;1796:4;1788:6;1784:17;1780:27;1770:2;;-1:-1;;1811:12;1770:2;1858:6;1845:20;33078:18;33070:6;33067:30;33064:2;;;-1:-1;;33100:12;33064:2;1880:60;33241:4;33173:9;1796:4;33158:6;33154:17;33150:33;33231:15;1880:60;;;1871:69;;1960:6;1953:5;1946:21;2064:3;33241:4;2055:6;1988;2046:16;;2043:25;2040:2;;;2081:1;;2071:12;2040:2;37579:6;33241:4;1988:6;1984:17;33241:4;2022:5;2018:16;37556:30;37635:1;37617:16;;;33241:4;37617:16;37610:27;2022:5;1763:375;-1:-1;;1763:375;5221:1071;;5329:4;5317:9;5312:3;5308:19;5304:30;5301:2;;;-1:-1;;5337:12;5301:2;5365:20;5329:4;5365:20;;;5356:29;;5453:17;5440:31;5491:18;;5483:6;5480:30;5477:2;;;5468:1;;5513:12;5477:2;5557:54;5607:3;5598:6;5587:9;5583:22;5557:54;;;5540:15;5533:79;5711:48;5755:3;5678:2;5735:9;5731:22;5711:48;;;5678:2;5697:5;5693:16;5686:74;5865:2;5854:9;5850:18;5837:32;5823:46;;5491:18;5881:6;5878:30;5875:2;;;5468:1;;5911:12;5875:2;5956:75;6027:3;6018:6;6007:9;6003:22;5956:75;;;5865:2;5942:5;5938:16;5931:101;6124:2;6113:9;6109:18;6096:32;6082:46;;5491:18;6140:6;6137:30;6134:2;;;5468:1;;6170:12;6134:2;;6215:55;6266:3;6257:6;6246:9;6242:22;6215:55;;;6124:2;6201:5;6197:16;6190:81;;5295:997;;;;;7550:128;7616:20;;37386:10;37375:22;;38666:34;;38656:2;;38714:1;;38704:12;38656:2;7601:77;;;;;7818:743;;;;;;7990:3;7978:9;7969:7;7965:23;7961:33;7958:2;;;-1:-1;;7997:12;7958:2;85:6;72:20;97:33;124:5;97:33;;;8049:63;-1:-1;8149:2;8188:22;;7480:20;;-1:-1;8257:2;8296:22;;7480:20;;-1:-1;8365:2;8404:22;;72:20;97:33;72:20;97:33;;;7952:609;;;;-1:-1;7952:609;;8473:3;8513:22;7480:20;;7952:609;-1:-1;;7952:609;8568:387;;8702:2;;8690:9;8681:7;8677:23;8673:32;8670:2;;;-1:-1;;8708:12;8670:2;8766:17;8753:31;8804:18;8796:6;8793:30;8790:2;;;-1:-1;;8826:12;8790:2;8922:6;8911:9;8907:22;989:3;982:4;974:6;970:17;966:27;956:2;;-1:-1;;997:12;956:2;1044:6;1031:20;1017:34;;1066:85;1081:69;1143:6;1081:69;;1066:85;1179:21;;;1236:14;;;;1211:17;;;-1:-1;1316:238;1341:6;1338:1;1335:13;1316:238;;;1448:42;1486:3;8702:2;1424:3;1411:17;1215:6;1399:30;;1448:42;;;1436:55;;1505:14;;;;1533;;;;1363:1;1356:9;1316:238;;;-1:-1;8846:93;;8664:291;-1:-1;;;;;;;;8664:291;8962:613;;;;;9115:3;9103:9;9094:7;9090:23;9086:33;9083:2;;;-1:-1;;9122:12;9083:2;1648:6;1635:20;9174:63;;9274:2;9315:9;9311:22;7750:20;37480:4;38813:5;37469:16;38790:5;38787:33;38777:2;;-1:-1;;38824:12;38777:2;9077:498;;9282:61;;-1:-1;;;;9380:2;9419:22;;1635:20;;9488:2;9527:22;1635:20;;9077:498;9582:345;;9695:2;9683:9;9674:7;9670:23;9666:32;9663:2;;;-1:-1;;9701:12;9663:2;9759:17;9746:31;9797:18;9789:6;9786:30;9783:2;;;-1:-1;;9819:12;9783:2;9849:62;9903:7;9894:6;9883:9;9879:22;9849:62;;;9839:72;9657:270;-1:-1;;;;9657:270;9934:239;;10037:2;10025:9;10016:7;10012:23;10008:32;10005:2;;;-1:-1;;10043:12;10005:2;-1:-1;2661:20;;9999:174;-1:-1;9999:174;10534:385;;10667:2;10655:9;10646:7;10642:23;10638:32;10635:2;;;-1:-1;;10673:12;10635:2;10731:17;10718:31;10769:18;;10761:6;10758:30;10755:2;;;-1:-1;;10791:12;10755:2;10886:6;10875:9;10871:22;3780:4;3768:9;3763:3;3759:19;3755:30;3752:2;;;-1:-1;;3788:12;3752:2;3816:20;3780:4;3816:20;;;3807:29;;3937:22;7480:20;3899:15;3892:74;10667:2;4043:9;4039:18;4026:32;10769:18;4070:6;4067:30;4064:2;;;-1:-1;;4100:12;4064:2;4145:54;4195:3;4186:6;4175:9;4171:22;4145:54;;;10667:2;4131:5;4127:16;4120:80;;4288:2;4277:9;4273:18;4260:32;10769:18;4304:6;4301:30;4298:2;;;-1:-1;;4334:12;4298:2;4379:55;4430:3;4421:6;4410:9;4406:22;4379:55;;;4288:2;4361:16;;4354:81;-1:-1;4365:5;;10629:290;-1:-1;;;;;10629:290;10926:385;;11059:2;11047:9;11038:7;11034:23;11030:32;11027:2;;;-1:-1;;11065:12;11027:2;11123:17;11110:31;11161:18;;11153:6;11150:30;11147:2;;;-1:-1;;11183:12;11147:2;11278:6;11267:9;11263:22;4619:4;4607:9;4602:3;4598:19;4594:30;4591:2;;;-1:-1;;4627:12;4591:2;4655:20;4619:4;4655:20;;;4646:29;;4745:17;4732:31;11161:18;4775:6;4772:30;4769:2;;;-1:-1;;4805:12;4769:2;4849:68;4913:3;4904:6;4893:9;4889:22;4849:68;;;4832:15;4825:93;;11059:2;5003:9;4999:18;4986:32;11161:18;5030:6;5027:30;5024:2;;;-1:-1;;5060:12;5024:2;5105:55;5156:3;5147:6;5136:9;5132:22;5105:55;;;11059:2;5087:16;;5080:81;-1:-1;5091:5;;11021:290;-1:-1;;;;;11021:290;11318:373;;11445:2;11433:9;11424:7;11420:23;11416:32;11413:2;;;-1:-1;;11451:12;11413:2;11509:17;11496:31;11547:18;11539:6;11536:30;11533:2;;;-1:-1;;11569:12;11533:2;11599:76;11667:7;11658:6;11647:9;11643:22;11599:76;;11946:701;;;;12103:2;12091:9;12082:7;12078:23;12074:32;12071:2;;;-1:-1;;12109:12;12071:2;7493:6;7480:20;12161:63;;12289:2;12278:9;12274:18;12261:32;12313:18;;12305:6;12302:30;12299:2;;;-1:-1;;12335:12;12299:2;12365:62;12419:7;12410:6;12399:9;12395:22;12365:62;;;12355:72;;12492:2;12481:9;12477:18;12464:32;12450:46;;12313:18;12508:6;12505:30;12502:2;;;-1:-1;;12538:12;12502:2;;12568:63;12623:7;12614:6;12603:9;12599:22;12568:63;;;12558:73;;;12065:582;;;;;;15443:343;;15585:5;34685:12;35771:6;35766:3;35759:19;15678:52;15723:6;35808:4;35803:3;35799:14;35808:4;15704:5;15700:16;15678:52;;;38097:2;38077:14;38093:7;38073:28;15742:39;;;;35808:4;15742:39;;15533:253;-1:-1;;15533:253;22988:1078;;23212:15;23206:22;23135:4;23248:13;23241:37;23293:67;23135:4;23130:3;23126:14;23341:12;23293:67;;;23450:4;;;37386:10;23450:4;23443:5;23439:16;23433:23;37375:22;23450:4;23512:3;23508:14;25494:36;23618:4;23611:5;23607:16;23601:23;23670:3;23664:4;23660:14;23618:4;23648:3;23644:14;23637:38;23690:109;13419:5;34685:12;35771:6;35766:3;35759:19;23450:4;35803:3;35799:14;13431:88;;23450:4;;13576:6;13572:17;35803:3;13563:27;;23450:4;13662:5;34361:14;-1:-1;13707:10;;13701:341;13726:6;13723:1;13720:13;13701:341;;;13778:20;35803:3;13782:4;13778:20;;13773:3;13766:33;12766:60;12822:3;13833:6;13827:13;12766:60;;;13748:1;13741:9;;;;;14021:14;;;;13847:82;-1:-1;35485:14;;13701:341;;;13705:14;23887:4;23880:5;23876:16;23870:23;23850:43;;23939:3;23933:4;23929:14;23887:4;23917:3;23913:14;23906:38;23959:69;24023:4;24009:12;23959:69;;;24050:11;23108:958;-1:-1;;;;;;;;;23108:958;25656:401;;15953:5;34685:12;16064:52;16109:6;16104:3;16097:4;16090:5;16086:16;16064:52;;;16128:16;;;;15235:37;;;-1:-1;16097:4;26020:12;;25809:248;-1:-1;25809:248;26064:213;37180:42;37169:54;;;;13153:37;;26182:2;26167:18;;26153:124;26284:437;;26490:2;;26479:9;26475:18;26490:2;26511:17;26504:47;26565:146;14406:5;34685:12;35771:6;35766:3;35759:19;35799:14;26479:9;35799:14;14418:112;;35799:14;26490:2;14587:6;14583:17;26479:9;14574:27;;14562:39;;26490:2;14691:5;34361:14;-1:-1;14730:387;14755:6;14752:1;14749:13;14730:387;;;14807:20;26479:9;14811:4;14807:20;;14802:3;14795:33;12980:88;13064:3;14862:6;14856:13;12980:88;;;14876:110;-1:-1;15096:14;;;;35485;;;;14777:1;14770:9;14730:387;;;-1:-1;26557:154;;26461:260;-1:-1;;;;;;;26461:260;26728:539;15235:37;;;37480:4;37469:16;;;;27087:2;27072:18;;25609:35;27170:2;27155:18;;15235:37;27253:2;27238:18;;15235:37;26926:3;26911:19;;26897:370;27274:691;;27504:2;27525:17;27518:47;27579:76;27504:2;27493:9;27489:18;27641:6;27579:76;;;27703:9;27697:4;27693:20;27688:2;27677:9;27673:18;27666:48;27728:76;27799:4;27790:6;27728:76;;;27852:9;27846:4;27842:20;27837:2;27826:9;27822:18;27815:48;27877:78;27950:4;27941:6;27877:78;;;27869:86;27475:490;-1:-1;;;;;;;27475:490;27972:293;;28106:2;28127:17;28120:47;28181:74;28106:2;28095:9;28091:18;28241:6;28181:74;;;28173:82;28077:188;-1:-1;;;28077:188;28272:710;28563:2;28577:47;;;18099:1;28548:18;;;35759:19;18134:66;35799:14;;;18114:87;18220:12;35808:4;28786:18;;28779:48;;;17729:1;18220:12;;;35759:19;17764:66;35799:14;;;17744:87;17850:12;;;28534:448;28989:407;29180:2;29194:47;;;18471:2;29165:18;;;35759:19;18507:66;35799:14;;;18487:87;18593:12;;;29151:245;29403:407;29594:2;29608:47;;;18844:2;29579:18;;;35759:19;18880:66;35799:14;;;18860:87;18966:12;;;29565:245;29817:381;;29995:2;30016:17;30009:47;20161:15;20155:22;20088:4;29995:2;29984:9;29980:18;20190:37;19281:15;19275:22;20079:14;29984:9;20079:14;15235:37;29995:2;19436:5;19432:16;19426:23;19210:4;19469:14;29984:9;19469:14;19462:38;19515:67;19201:14;29984:9;19201:14;19563:12;19515:67;;;19666:4;19659:5;19655:16;19649:23;19629:43;;19708:14;29984:9;19712:4;19708:14;;19692;29984:9;19692:14;19685:38;19738:69;19802:4;19788:12;19738:69;;;19829:11;;;;29995:2;20428:5;20424:16;20418:23;20477:14;;29984:9;20481:4;20477:14;;19666:4;29984:9;20461:14;20454:38;20507:67;20569:4;20555:12;20507:67;;;19666:4;20653:5;20649:16;20643:23;20623:43;;20477:14;29984:9;20706:4;20702:14;;19210:4;29984:9;20686:14;20679:38;20732:67;20794:4;20780:12;20732:67;;;20724:75;;;19210:4;20878:5;20874:16;20868:23;20848:43;;20477:14;29984:9;20931:4;20927:14;;20088:4;29984:9;20911:14;20904:38;;20957:69;21021:4;21007:12;20957:69;;;30062:126;29966:232;-1:-1;;;;;29966:232;30205:453;21492:22;;22809;15235:37;;30443:2;30428:18;;30414:244;30665:377;;30841:2;30862:17;30855:47;22009:15;22003:22;21930:4;30841:2;30830:9;30826:18;22038:37;22090:95;21921:14;30830:9;21921:14;22166:12;22090:95;;;30841:2;22270:5;22266:16;22260:23;22240:43;;22319:14;30830:9;22323:4;22319:14;;21930:4;30830:9;22303:14;22296:38;22349:69;22413:4;22399:12;22349:69;;31049:353;;31213:2;31234:17;31227:47;31288:104;31213:2;31202:9;31198:18;31378:6;31288:104;;31409:213;15235:37;;;31527:2;31512:18;;31498:124;31629:412;;15265:5;15242:3;15235:37;31795:2;31913;31902:9;31898:18;31891:48;31953:78;31795:2;31784:9;31780:18;32017:6;31953:78;;32048:256;32110:2;32104:9;32136:17;;;32211:18;32196:34;;32232:22;;;32193:62;32190:2;;;32268:1;;32258:12;32190:2;32110;32277:22;32088:216;;-1:-1;32088:216;32311:305;;32471:18;32463:6;32460:30;32457:2;;;-1:-1;;32493:12;32457:2;-1:-1;32538:4;32526:17;;;32591:15;;32394:222;37652:268;37717:1;37724:101;37738:6;37735:1;37732:13;37724:101;;;37805:11;;;37799:18;37786:11;;;37779:39;37760:2;37753:10;37724:101;;;37840:6;37837:1;37834:13;37831:2;;;37717:1;37896:6;37891:3;37887:16;37880:27;37831:2;;37701:219;;;;38114:117;37180:42;38201:5;37169:54;38176:5;38173:35;38163:2;;38222:1;;38212:12" + "object": "0x608060405234801561001057600080fd5b50600436106101ef5760003560e01c806377ec31ae1161010f578063bdab1688116100a2578063e796ee9611610071578063e796ee96146103c7578063ee8b86fb146103d5578063f408fb311461028f578063fa315f9d146103e8576101ef565b8063bdab16881461038d578063cd3c0b97146103a2578063d6d7618c146103aa578063d88be12f146103bf576101ef565b80639a3b6185116100de5780639a3b618514610359578063a3c2f6b614610361578063ae2dae1714610369578063bb60736214610377576101ef565b806377ec31ae146103105780637833bec01461031e5780637a791e6e1461033e5780638ee52b4e14610346576101ef565b80634582eab2116101875780635ba3c7c0116101565780635ba3c7c0146102df57806363d69c88146102e7578063647341eb146102fa57806376f15d5b14610308576101ef565b80634582eab2146102a557806345fdbdb7146102ad578063586f84b2146102b557806359c28add146102ca576101ef565b80633687617d116101c35780633687617d1461024d57806336b323961461026f5780633e9ef66a1461028f5780634303a5421461029d576101ef565b806209e437146101f45780630527c28f146101fe5780631310e444146102115780632e1a7d4d1461023a575b600080fd5b6101fc6103f6565b005b6101fc61020c366004610d98565b610433565b61022461021f366004610ec5565b610436565b6040516102319190611526565b60405180910390f35b6101fc610248366004610ec5565b61043d565b61026061025b36600461103a565b61048e565b6040516102319392919061128f565b61028261027d366004610e51565b61052e565b60405161023191906111d2565b6101fc61020c366004610e92565b610224610610565b6101fc610617565b6101fc61067c565b6102bd6106ae565b60405161023191906114b1565b6102d26106b6565b60405161023191906114bc565b6101fc6106be565b6102826102f5366004610cbb565b610723565b6101fc61020c366004611007565b61022461072c565b6101fc61020c366004610e16565b61033161032c366004610edd565b61073a565b60405161023191906113c5565b6101fc6107f7565b610224610354366004610ec5565b6107fc565b6101fc610802565b61022461080d565b6101fc61020c366004610f77565b61037f610812565b60405161023192919061152f565b61039561084b565b60405161023191906111f3565b6101fc610850565b6103b2610887565b6040516102319190611513565b6102246109e0565b6101fc61020c366004610d0c565b6101fc6103e3366004610ec5565b61020c565b6101fc61020c366004610ec5565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104289061138e565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040516104839190611526565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161057f9291906111b0565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105ba9493929190611271565b6020604051602081039080840390855afa1580156105dc573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042890611357565b6106146109e6565b6106146109fe565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b50929392505050565b600080546001019081905590565b610742610a1e565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b610431565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161087d906112eb565b60405180910390a1565b61088f610a4c565b6040805160028082526060828101909352816020015b60608152602001906001900390816108a55790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108ff57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061094d57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109f9610a7a565b905290565b6040518060400160405280610a11610a4c565b8152602001606081525090565b6040518060800160405280610a31610a8d565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610abe578081fd5b8135610ad1610acc8261156f565b611548565b8181529150602080830190840160005b83811015610b0e57610af98760208435890101610b73565b83526020928301929190910190600101610ae1565b5050505092915050565b600082601f830112610b28578081fd5b8135610b36610acc8261156f565b8181529150602080830190840160005b83811015610b0e57610b5e8760208435890101610bfa565b83526020928301929190910190600101610b46565b600082601f830112610b83578081fd5b813567ffffffffffffffff811115610b99578182fd5b610bca60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611548565b9150808252836020828501011115610be157600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610c0b578081fd5b610c156080611548565b9050813567ffffffffffffffff80821115610c2f57600080fd5b610c3b85838601610b73565b8352610c4a8560208601610ca1565b60208401526040840135915080821115610c6357600080fd5b610c6f85838601610aae565b60408401526060840135915080821115610c8857600080fd5b50610c9584828501610b73565b60608301525092915050565b803563ffffffff81168114610cb557600080fd5b92915050565b600080600080600060a08688031215610cd2578081fd5b8535610cdd816115bf565b945060208601359350604086013592506060860135610cfb816115bf565b949793965091946080013592915050565b60006020808385031215610d1e578182fd5b823567ffffffffffffffff811115610d34578283fd5b80840185601f820112610d45578384fd5b80359150610d55610acc8361156f565b82815283810190828501865b85811015610d8a57610d788a888435880101610b18565b84529286019290860190600101610d61565b509098975050505050505050565b60006020808385031215610daa578182fd5b823567ffffffffffffffff811115610dc0578283fd5b80840185601f820112610dd1578384fd5b80359150610de1610acc8361156f565b82815283810190828501865b85811015610d8a57610e048a888435880101610b73565b84529286019290860190600101610ded565b600060208284031215610e27578081fd5b813567ffffffffffffffff811115610e3d578182fd5b610e4984828501610b18565b949350505050565b60008060008060808587031215610e66578182fd5b84359350602085013560ff81168114610e7d578283fd5b93969395505050506040820135916060013590565b600060208284031215610ea3578081fd5b813567ffffffffffffffff811115610eb9578182fd5b610e4984828501610b73565b600060208284031215610ed6578081fd5b5035919050565b600060208284031215610eee578081fd5b813567ffffffffffffffff80821115610f05578283fd5b81840160608187031215610f17578384fd5b610f216060611548565b925080358352602081013582811115610f38578485fd5b610f4487828401610b73565b602085015250604081013582811115610f5b578485fd5b610f6787828401610b73565b6040850152509195945050505050565b600060208284031215610f88578081fd5b813567ffffffffffffffff80821115610f9f578283fd5b81840160408187031215610fb1578384fd5b610fbb6040611548565b9250803582811115610fcb578485fd5b610fd787828401610bfa565b845250602081013582811115610feb578485fd5b610ff787828401610b73565b6020850152509195945050505050565b600060208284031215611018578081fd5b813567ffffffffffffffff81111561102e578182fd5b610e4984828501610bfa565b60008060006060848603121561104e578081fd5b83359250602084013567ffffffffffffffff8082111561106c578283fd5b61107887838801610b73565b9350604086013591508082111561108d578283fd5b5061109a86828701610b73565b9150509250925092565b600081518084526110bc81602086016020860161158f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081516080845261110360808501826110a4565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b82851015611189577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08683030184526111758282516110a4565b60019590950194938701939150860161113b565b506060880151955088810360608a01526111a381876110a4565b9998505050505050505050565b600083516111c281846020880161158f565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611264577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526112528583516110ee565b94509285019290850190600101611218565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526112a260608301866110a4565b82810360208401526112b481866110a4565b83810360408501526112c681866110a4565b979650505050505050565b6000602082526112e460208301846110a4565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526113f56101008501826110a4565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e086015261143081836110a4565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085840301604086015261146e83836110a4565b604087015193508186820301606087015261148981856110a4565b9250506060860151925080858303016080860152506114a881836110a4565b95945050505050565b905151815260200190565b6000602082528251604060208401526114d860608401826110ee565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526114a881836110a4565b6000602082526112e460208301846110ee565b90815260200190565b600083825260406020830152610e4960408301846110a4565b60405181810167ffffffffffffffff8111828210171561156757600080fd5b604052919050565b600067ffffffffffffffff821115611585578081fd5b5060209081020190565b60005b838110156115aa578181015183820152602001611592565b838111156115b9576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461043357600080fdfea365627a7a72315820d4953afa8fe277a67a582a705ec911d7c404b5a84176ab0e36aa14da0e5986326c6578706572696d656e74616cf564736f6c63430005100040", + "opcodes": "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH2 0x1EF JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0x77EC31AE GT PUSH2 0x10F JUMPI DUP1 PUSH4 0xBDAB1688 GT PUSH2 0xA2 JUMPI DUP1 PUSH4 0xE796EE96 GT PUSH2 0x71 JUMPI DUP1 PUSH4 0xE796EE96 EQ PUSH2 0x3C7 JUMPI DUP1 PUSH4 0xEE8B86FB EQ PUSH2 0x3D5 JUMPI DUP1 PUSH4 0xF408FB31 EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0xFA315F9D EQ PUSH2 0x3E8 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0xBDAB1688 EQ PUSH2 0x38D JUMPI DUP1 PUSH4 0xCD3C0B97 EQ PUSH2 0x3A2 JUMPI DUP1 PUSH4 0xD6D7618C EQ PUSH2 0x3AA JUMPI DUP1 PUSH4 0xD88BE12F EQ PUSH2 0x3BF JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x9A3B6185 GT PUSH2 0xDE JUMPI DUP1 PUSH4 0x9A3B6185 EQ PUSH2 0x359 JUMPI DUP1 PUSH4 0xA3C2F6B6 EQ PUSH2 0x361 JUMPI DUP1 PUSH4 0xAE2DAE17 EQ PUSH2 0x369 JUMPI DUP1 PUSH4 0xBB607362 EQ PUSH2 0x377 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x77EC31AE EQ PUSH2 0x310 JUMPI DUP1 PUSH4 0x7833BEC0 EQ PUSH2 0x31E JUMPI DUP1 PUSH4 0x7A791E6E EQ PUSH2 0x33E JUMPI DUP1 PUSH4 0x8EE52B4E EQ PUSH2 0x346 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 GT PUSH2 0x187 JUMPI DUP1 PUSH4 0x5BA3C7C0 GT PUSH2 0x156 JUMPI DUP1 PUSH4 0x5BA3C7C0 EQ PUSH2 0x2DF JUMPI DUP1 PUSH4 0x63D69C88 EQ PUSH2 0x2E7 JUMPI DUP1 PUSH4 0x647341EB EQ PUSH2 0x2FA JUMPI DUP1 PUSH4 0x76F15D5B EQ PUSH2 0x308 JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x4582EAB2 EQ PUSH2 0x2A5 JUMPI DUP1 PUSH4 0x45FDBDB7 EQ PUSH2 0x2AD JUMPI DUP1 PUSH4 0x586F84B2 EQ PUSH2 0x2B5 JUMPI DUP1 PUSH4 0x59C28ADD EQ PUSH2 0x2CA JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH4 0x3687617D GT PUSH2 0x1C3 JUMPI DUP1 PUSH4 0x3687617D EQ PUSH2 0x24D JUMPI DUP1 PUSH4 0x36B32396 EQ PUSH2 0x26F JUMPI DUP1 PUSH4 0x3E9EF66A EQ PUSH2 0x28F JUMPI DUP1 PUSH4 0x4303A542 EQ PUSH2 0x29D JUMPI PUSH2 0x1EF JUMP JUMPDEST DUP1 PUSH3 0x9E437 EQ PUSH2 0x1F4 JUMPI DUP1 PUSH4 0x527C28F EQ PUSH2 0x1FE JUMPI DUP1 PUSH4 0x1310E444 EQ PUSH2 0x211 JUMPI DUP1 PUSH4 0x2E1A7D4D EQ PUSH2 0x23A JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x1FC PUSH2 0x3F6 JUMP JUMPDEST STOP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xD98 JUMP JUMPDEST PUSH2 0x433 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x21F CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x436 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x1526 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x1FC PUSH2 0x248 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x43D JUMP JUMPDEST PUSH2 0x260 PUSH2 0x25B CALLDATASIZE PUSH1 0x4 PUSH2 0x103A JUMP JUMPDEST PUSH2 0x48E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x128F JUMP JUMPDEST PUSH2 0x282 PUSH2 0x27D CALLDATASIZE PUSH1 0x4 PUSH2 0xE51 JUMP JUMPDEST PUSH2 0x52E JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x11D2 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xE92 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x610 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x617 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x67C JUMP JUMPDEST PUSH2 0x2BD PUSH2 0x6AE JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x14B1 JUMP JUMPDEST PUSH2 0x2D2 PUSH2 0x6B6 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x14BC JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x6BE JUMP JUMPDEST PUSH2 0x282 PUSH2 0x2F5 CALLDATASIZE PUSH1 0x4 PUSH2 0xCBB JUMP JUMPDEST PUSH2 0x723 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0x1007 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x72C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xE16 JUMP JUMPDEST PUSH2 0x331 PUSH2 0x32C CALLDATASIZE PUSH1 0x4 PUSH2 0xEDD JUMP JUMPDEST PUSH2 0x73A JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x13C5 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x7F7 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x354 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x7FC JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x802 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x80D JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xF77 JUMP JUMPDEST PUSH2 0x37F PUSH2 0x812 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP3 SWAP2 SWAP1 PUSH2 0x152F JUMP JUMPDEST PUSH2 0x395 PUSH2 0x84B JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x11F3 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x850 JUMP JUMPDEST PUSH2 0x3B2 PUSH2 0x887 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH2 0x231 SWAP2 SWAP1 PUSH2 0x1513 JUMP JUMPDEST PUSH2 0x224 PUSH2 0x9E0 JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xD0C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x3E3 CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH2 0x20C JUMP JUMPDEST PUSH2 0x1FC PUSH2 0x20C CALLDATASIZE PUSH1 0x4 PUSH2 0xEC5 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x428 SWAP1 PUSH2 0x138E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 REVERT JUMPDEST JUMP JUMPDEST POP JUMP JUMPDEST POP PUSH2 0x7C7 SWAP1 JUMP JUMPDEST CALLER PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AND PUSH32 0x7FCF532C15F0A6DB0BD6D0E038BEA71D30D808C7D98CB3BF7268A95BF5081B65 DUP3 PUSH1 0x40 MLOAD PUSH2 0x483 SWAP2 SWAP1 PUSH2 0x1526 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG2 POP JUMP JUMPDEST POP POP PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP1 DUP5 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP4 MLOAD DUP1 DUP6 ADD DUP6 MSTORE DUP3 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP4 ADD MSTORE DUP5 MLOAD DUP1 DUP7 ADD SWAP1 SWAP6 MSTORE SWAP2 DUP5 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP5 ADD MSTORE SWAP1 SWAP4 SWAP1 SWAP3 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x1C DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x19457468657265756D205369676E6564204D6573736167653A0A333200000000 DUP2 MSTORE POP SWAP1 POP PUSH1 0x0 DUP2 DUP8 PUSH1 0x40 MLOAD PUSH1 0x20 ADD PUSH2 0x57F SWAP3 SWAP2 SWAP1 PUSH2 0x11B0 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 DUP4 SUB SUB DUP2 MSTORE SWAP1 PUSH1 0x40 MSTORE DUP1 MLOAD SWAP1 PUSH1 0x20 ADD KECCAK256 SWAP1 POP PUSH1 0x1 DUP2 DUP8 DUP8 DUP8 PUSH1 0x40 MLOAD PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x40 MSTORE PUSH1 0x40 MLOAD PUSH2 0x5BA SWAP5 SWAP4 SWAP3 SWAP2 SWAP1 PUSH2 0x1271 JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD PUSH1 0x20 DUP2 SUB SWAP1 DUP1 DUP5 SUB SWAP1 DUP6 GAS STATICCALL ISZERO DUP1 ISZERO PUSH2 0x5DC JUMPI RETURNDATASIZE PUSH1 0x0 DUP1 RETURNDATACOPY RETURNDATASIZE PUSH1 0x0 REVERT JUMPDEST POP POP PUSH1 0x40 MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 ADD MLOAD SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH2 0x7C7 JUMPDEST SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x14 DUP2 MSTORE PUSH32 0x5245564552545F574954485F434F4E5354414E54000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x428 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x12D1 JUMP JUMPDEST PUSH1 0x40 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH1 0x4 ADD PUSH2 0x428 SWAP1 PUSH2 0x1357 JUMP JUMPDEST PUSH2 0x614 PUSH2 0x9E6 JUMP JUMPDEST PUSH2 0x614 PUSH2 0x9FE JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x15 DUP2 MSTORE PUSH32 0x524551554952455F574954485F434F4E5354414E540000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE SWAP1 MLOAD PUSH32 0x8C379A000000000000000000000000000000000000000000000000000000000 DUP2 MSTORE PUSH2 0x428 SWAP2 SWAP1 PUSH1 0x4 ADD PUSH2 0x12D1 JUMP JUMPDEST POP SWAP3 SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 DUP2 SWAP1 SSTORE SWAP1 JUMP JUMPDEST PUSH2 0x742 PUSH2 0xA1E JUMP JUMPDEST POP PUSH1 0x40 DUP1 MLOAD PUSH1 0x80 DUP2 ADD DUP3 MSTORE SWAP2 DUP3 MSTORE DUP1 MLOAD DUP1 DUP3 ADD DUP3 MSTORE PUSH1 0x4 DUP1 DUP3 MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP4 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE DUP1 DUP6 ADD SWAP3 SWAP1 SWAP3 MSTORE DUP3 MLOAD DUP1 DUP5 ADD DUP5 MSTORE DUP2 DUP2 MSTORE PUSH32 0x8765432100000000000000000000000000000000000000000000000000000000 DUP2 DUP5 ADD MSTORE DUP5 DUP5 ADD MSTORE DUP3 MLOAD DUP1 DUP5 ADD SWAP1 SWAP4 MSTORE DUP3 MSTORE PUSH32 0x616D657400000000000000000000000000000000000000000000000000000000 SWAP1 DUP3 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 JUMP JUMPDEST PUSH2 0x431 JUMP JUMPDEST PUSH1 0x1 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD PUSH1 0x1 ADD SWAP1 SSTORE JUMP JUMPDEST PUSH1 0x1 SWAP1 JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x5 DUP2 MSTORE PUSH32 0x68656C6C6F000000000000000000000000000000000000000000000000000000 PUSH1 0x20 DUP3 ADD MSTORE PUSH1 0x1 SWAP2 JUMP JUMPDEST PUSH1 0x60 SWAP1 JUMP JUMPDEST PUSH32 0x61A6029A4C7DDEE5824D171331EECBD015D26A271310A223718B837FACB5B771 PUSH1 0x40 MLOAD PUSH2 0x87D SWAP1 PUSH2 0x12EB JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 LOG1 JUMP JUMPDEST PUSH2 0x88F PUSH2 0xA4C JUMP JUMPDEST PUSH1 0x40 DUP1 MLOAD PUSH1 0x2 DUP1 DUP3 MSTORE PUSH1 0x60 DUP3 DUP2 ADD SWAP1 SWAP4 MSTORE DUP2 PUSH1 0x20 ADD JUMPDEST PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 PUSH1 0x1 SWAP1 SUB SWAP1 DUP2 PUSH2 0x8A5 JUMPI SWAP1 POP POP SWAP1 POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x0 DUP2 MLOAD DUP2 LT PUSH2 0x8FF JUMPI INVALID JUMPDEST PUSH1 0x20 MUL PUSH1 0x20 ADD ADD DUP2 SWAP1 MSTORE POP PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x5 DUP2 MSTORE PUSH1 0x20 ADD PUSH32 0x3078333231000000000000000000000000000000000000000000000000000000 DUP2 MSTORE POP DUP2 PUSH1 0x1 DUP2 MLOAD DUP2 LT PUSH2 0x94D JUMPI INVALID JUMPDEST PUSH1 0x20 SWAP1 DUP2 MUL SWAP2 SWAP1 SWAP2 ADD DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x40 DUP1 MLOAD PUSH1 0xC0 DUP2 ADD DUP3 MSTORE PUSH1 0x5 PUSH1 0x80 DUP3 ADD DUP2 DUP2 MSTORE PUSH32 0x3078313233000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP5 ADD MSTORE DUP3 MSTORE DUP2 DUP5 ADD MSTORE DUP1 DUP3 ADD SWAP4 SWAP1 SWAP4 MSTORE DUP1 MLOAD DUP1 DUP3 ADD SWAP1 SWAP2 MSTORE PUSH1 0x3 DUP2 MSTORE PUSH32 0x6162630000000000000000000000000000000000000000000000000000000000 SWAP2 DUP2 ADD SWAP2 SWAP1 SWAP2 MSTORE PUSH1 0x60 DUP3 ADD MSTORE SWAP1 POP SWAP1 JUMP JUMPDEST PUSH2 0x4D2 SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0x9F9 PUSH2 0xA7A JUMP JUMPDEST SWAP1 MSTORE SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x40 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0xA11 PUSH2 0xA4C JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH2 0xA31 PUSH2 0xA8D JUMP JUMPDEST DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x80 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 PUSH4 0xFFFFFFFF AND DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x20 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 PUSH1 0x60 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x60 DUP2 MSTORE POP SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xABE JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xAD1 PUSH2 0xACC DUP3 PUSH2 0x156F JUMP JUMPDEST PUSH2 0x1548 JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB0E JUMPI PUSH2 0xAF9 DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xB73 JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xAE1 JUMP JUMPDEST POP POP POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xB28 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH2 0xB36 PUSH2 0xACC DUP3 PUSH2 0x156F JUMP JUMPDEST DUP2 DUP2 MSTORE SWAP2 POP PUSH1 0x20 DUP1 DUP4 ADD SWAP1 DUP5 ADD PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xB0E JUMPI PUSH2 0xB5E DUP8 PUSH1 0x20 DUP5 CALLDATALOAD DUP10 ADD ADD PUSH2 0xBFA JUMP JUMPDEST DUP4 MSTORE PUSH1 0x20 SWAP3 DUP4 ADD SWAP3 SWAP2 SWAP1 SWAP2 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xB46 JUMP JUMPDEST PUSH1 0x0 DUP3 PUSH1 0x1F DUP4 ADD SLT PUSH2 0xB83 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xB99 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xBCA PUSH1 0x20 PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 PUSH1 0x1F DUP5 ADD AND ADD PUSH2 0x1548 JUMP JUMPDEST SWAP2 POP DUP1 DUP3 MSTORE DUP4 PUSH1 0x20 DUP3 DUP6 ADD ADD GT ISZERO PUSH2 0xBE1 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP1 PUSH1 0x20 DUP5 ADD PUSH1 0x20 DUP5 ADD CALLDATACOPY PUSH1 0x0 SWAP1 DUP3 ADD PUSH1 0x20 ADD MSTORE SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x80 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xC0B JUMPI DUP1 DUP2 REVERT JUMPDEST PUSH2 0xC15 PUSH1 0x80 PUSH2 0x1548 JUMP JUMPDEST SWAP1 POP DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xC2F JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC3B DUP6 DUP4 DUP7 ADD PUSH2 0xB73 JUMP JUMPDEST DUP4 MSTORE PUSH2 0xC4A DUP6 PUSH1 0x20 DUP7 ADD PUSH2 0xCA1 JUMP JUMPDEST PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xC63 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xC6F DUP6 DUP4 DUP7 ADD PUSH2 0xAAE JUMP JUMPDEST PUSH1 0x40 DUP5 ADD MSTORE PUSH1 0x60 DUP5 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0xC88 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH2 0xC95 DUP5 DUP3 DUP6 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x60 DUP4 ADD MSTORE POP SWAP3 SWAP2 POP POP JUMP JUMPDEST DUP1 CALLDATALOAD PUSH4 0xFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0xCB5 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0xA0 DUP7 DUP9 SUB SLT ISZERO PUSH2 0xCD2 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP6 CALLDATALOAD PUSH2 0xCDD DUP2 PUSH2 0x15BF JUMP JUMPDEST SWAP5 POP PUSH1 0x20 DUP7 ADD CALLDATALOAD SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP3 POP PUSH1 0x60 DUP7 ADD CALLDATALOAD PUSH2 0xCFB DUP2 PUSH2 0x15BF JUMP JUMPDEST SWAP5 SWAP8 SWAP4 SWAP7 POP SWAP2 SWAP5 PUSH1 0x80 ADD CALLDATALOAD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xD1E JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xD34 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xD45 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xD55 PUSH2 0xACC DUP4 PUSH2 0x156F JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xD8A JUMPI PUSH2 0xD78 DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xB18 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xD61 JUMP JUMPDEST POP SWAP1 SWAP9 SWAP8 POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 DUP6 SUB SLT ISZERO PUSH2 0xDAA JUMPI DUP2 DUP3 REVERT JUMPDEST DUP3 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xDC0 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP1 DUP5 ADD DUP6 PUSH1 0x1F DUP3 ADD SLT PUSH2 0xDD1 JUMPI DUP4 DUP5 REVERT JUMPDEST DUP1 CALLDATALOAD SWAP2 POP PUSH2 0xDE1 PUSH2 0xACC DUP4 PUSH2 0x156F JUMP JUMPDEST DUP3 DUP2 MSTORE DUP4 DUP2 ADD SWAP1 DUP3 DUP6 ADD DUP7 JUMPDEST DUP6 DUP2 LT ISZERO PUSH2 0xD8A JUMPI PUSH2 0xE04 DUP11 DUP9 DUP5 CALLDATALOAD DUP9 ADD ADD PUSH2 0xB73 JUMP JUMPDEST DUP5 MSTORE SWAP3 DUP7 ADD SWAP3 SWAP1 DUP7 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0xDED JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xE27 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xE3D JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xB18 JUMP JUMPDEST SWAP5 SWAP4 POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 DUP1 PUSH1 0x80 DUP6 DUP8 SUB SLT ISZERO PUSH2 0xE66 JUMPI DUP2 DUP3 REVERT JUMPDEST DUP5 CALLDATALOAD SWAP4 POP PUSH1 0x20 DUP6 ADD CALLDATALOAD PUSH1 0xFF DUP2 AND DUP2 EQ PUSH2 0xE7D JUMPI DUP3 DUP4 REVERT JUMPDEST SWAP4 SWAP7 SWAP4 SWAP6 POP POP POP POP PUSH1 0x40 DUP3 ADD CALLDATALOAD SWAP2 PUSH1 0x60 ADD CALLDATALOAD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEA3 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0xEB9 JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xED6 JUMPI DUP1 DUP2 REVERT JUMPDEST POP CALLDATALOAD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xEEE JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF05 JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x60 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xF17 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xF21 PUSH1 0x60 PUSH2 0x1548 JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP4 MSTORE PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xF38 JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xF44 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP PUSH1 0x40 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xF5B JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xF67 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x40 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0xF88 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0xF9F JUMPI DUP3 DUP4 REVERT JUMPDEST DUP2 DUP5 ADD PUSH1 0x40 DUP2 DUP8 SUB SLT ISZERO PUSH2 0xFB1 JUMPI DUP4 DUP5 REVERT JUMPDEST PUSH2 0xFBB PUSH1 0x40 PUSH2 0x1548 JUMP JUMPDEST SWAP3 POP DUP1 CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xFCB JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xFD7 DUP8 DUP3 DUP5 ADD PUSH2 0xBFA JUMP JUMPDEST DUP5 MSTORE POP PUSH1 0x20 DUP2 ADD CALLDATALOAD DUP3 DUP2 GT ISZERO PUSH2 0xFEB JUMPI DUP5 DUP6 REVERT JUMPDEST PUSH2 0xFF7 DUP8 DUP3 DUP5 ADD PUSH2 0xB73 JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MSTORE POP SWAP2 SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 DUP5 SUB SLT ISZERO PUSH2 0x1018 JUMPI DUP1 DUP2 REVERT JUMPDEST DUP2 CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT ISZERO PUSH2 0x102E JUMPI DUP2 DUP3 REVERT JUMPDEST PUSH2 0xE49 DUP5 DUP3 DUP6 ADD PUSH2 0xBFA JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH1 0x0 PUSH1 0x60 DUP5 DUP7 SUB SLT ISZERO PUSH2 0x104E JUMPI DUP1 DUP2 REVERT JUMPDEST DUP4 CALLDATALOAD SWAP3 POP PUSH1 0x20 DUP5 ADD CALLDATALOAD PUSH8 0xFFFFFFFFFFFFFFFF DUP1 DUP3 GT ISZERO PUSH2 0x106C JUMPI DUP3 DUP4 REVERT JUMPDEST PUSH2 0x1078 DUP8 DUP4 DUP9 ADD PUSH2 0xB73 JUMP JUMPDEST SWAP4 POP PUSH1 0x40 DUP7 ADD CALLDATALOAD SWAP2 POP DUP1 DUP3 GT ISZERO PUSH2 0x108D JUMPI DUP3 DUP4 REVERT JUMPDEST POP PUSH2 0x109A DUP7 DUP3 DUP8 ADD PUSH2 0xB73 JUMP JUMPDEST SWAP2 POP POP SWAP3 POP SWAP3 POP SWAP3 JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD DUP1 DUP5 MSTORE PUSH2 0x10BC DUP2 PUSH1 0x20 DUP7 ADD PUSH1 0x20 DUP7 ADD PUSH2 0x158F JUMP JUMPDEST PUSH1 0x1F ADD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 AND SWAP3 SWAP1 SWAP3 ADD PUSH1 0x20 ADD SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP2 MLOAD PUSH1 0x80 DUP5 MSTORE PUSH2 0x1103 PUSH1 0x80 DUP6 ADD DUP3 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x20 SWAP2 POP PUSH4 0xFFFFFFFF DUP3 DUP6 ADD MLOAD AND DUP3 DUP7 ADD MSTORE PUSH1 0x40 DUP5 ADD MLOAD DUP6 DUP3 SUB PUSH1 0x40 DUP8 ADD MSTORE DUP2 DUP2 MLOAD DUP1 DUP5 MSTORE DUP5 DUP5 ADD SWAP2 POP DUP5 DUP6 DUP3 MUL DUP6 ADD ADD DUP6 DUP5 ADD DUP8 SWAP5 POP JUMPDEST DUP3 DUP6 LT ISZERO PUSH2 0x1189 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP7 DUP4 SUB ADD DUP5 MSTORE PUSH2 0x1175 DUP3 DUP3 MLOAD PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x1 SWAP6 SWAP1 SWAP6 ADD SWAP5 SWAP4 DUP8 ADD SWAP4 SWAP2 POP DUP7 ADD PUSH2 0x113B JUMP JUMPDEST POP PUSH1 0x60 DUP9 ADD MLOAD SWAP6 POP DUP9 DUP2 SUB PUSH1 0x60 DUP11 ADD MSTORE PUSH2 0x11A3 DUP2 DUP8 PUSH2 0x10A4 JUMP JUMPDEST SWAP10 SWAP9 POP POP POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 DUP4 MLOAD PUSH2 0x11C2 DUP2 DUP5 PUSH1 0x20 DUP9 ADD PUSH2 0x158F JUMP JUMPDEST SWAP2 SWAP1 SWAP2 ADD SWAP2 DUP3 MSTORE POP PUSH1 0x20 ADD SWAP2 SWAP1 POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF SWAP2 SWAP1 SWAP2 AND DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP1 DUP4 ADD DUP2 DUP5 MSTORE DUP1 DUP6 MLOAD DUP1 DUP4 MSTORE PUSH1 0x40 DUP7 ADD SWAP2 POP PUSH1 0x40 DUP5 DUP3 MUL DUP8 ADD ADD SWAP3 POP DUP4 DUP8 ADD DUP6 JUMPDEST DUP3 DUP2 LT ISZERO PUSH2 0x1264 JUMPI PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 DUP9 DUP7 SUB ADD DUP5 MSTORE PUSH2 0x1252 DUP6 DUP4 MLOAD PUSH2 0x10EE JUMP JUMPDEST SWAP5 POP SWAP3 DUP6 ADD SWAP3 SWAP1 DUP6 ADD SWAP1 PUSH1 0x1 ADD PUSH2 0x1218 JUMP JUMPDEST POP SWAP3 SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST SWAP4 DUP5 MSTORE PUSH1 0xFF SWAP3 SWAP1 SWAP3 AND PUSH1 0x20 DUP5 ADD MSTORE PUSH1 0x40 DUP4 ADD MSTORE PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x60 DUP3 MSTORE PUSH2 0x12A2 PUSH1 0x60 DUP4 ADD DUP7 PUSH2 0x10A4 JUMP JUMPDEST DUP3 DUP2 SUB PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x12B4 DUP2 DUP7 PUSH2 0x10A4 JUMP JUMPDEST DUP4 DUP2 SUB PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x12C6 DUP2 DUP7 PUSH2 0x10A4 JUMP JUMPDEST SWAP8 SWAP7 POP POP POP POP POP POP POP JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x12E4 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x10A4 JUMP JUMPDEST SWAP4 SWAP3 POP POP POP JUMP JUMPDEST PUSH1 0x40 DUP1 DUP3 MSTORE PUSH1 0x4 SWAP1 DUP3 ADD MSTORE PUSH32 0x1234567800000000000000000000000000000000000000000000000000000000 PUSH1 0x60 DUP3 ADD MSTORE PUSH1 0x80 PUSH1 0x20 DUP3 ADD DUP2 SWAP1 MSTORE PUSH1 0x5 SWAP1 DUP3 ADD MSTORE PUSH32 0x6C6F72656D000000000000000000000000000000000000000000000000000000 PUSH1 0xA0 DUP3 ADD MSTORE PUSH1 0xC0 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xD SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455645525400000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x20 DUP1 DUP3 MSTORE PUSH1 0xE SWAP1 DUP3 ADD MSTORE PUSH32 0x53494D504C455F52455155495245000000000000000000000000000000000000 PUSH1 0x40 DUP3 ADD MSTORE PUSH1 0x60 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x80 PUSH1 0x20 DUP5 ADD MSTORE DUP1 MLOAD PUSH1 0xA0 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD MLOAD PUSH1 0x60 PUSH1 0xC0 DUP6 ADD MSTORE PUSH2 0x13F5 PUSH2 0x100 DUP6 ADD DUP3 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 DUP4 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 DUP6 DUP3 SUB ADD PUSH1 0xE0 DUP7 ADD MSTORE PUSH2 0x1430 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST SWAP3 POP POP POP PUSH1 0x20 DUP5 ADD MLOAD PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP1 DUP6 DUP5 SUB ADD PUSH1 0x40 DUP7 ADD MSTORE PUSH2 0x146E DUP4 DUP4 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 DUP8 ADD MLOAD SWAP4 POP DUP2 DUP7 DUP3 SUB ADD PUSH1 0x60 DUP8 ADD MSTORE PUSH2 0x1489 DUP2 DUP6 PUSH2 0x10A4 JUMP JUMPDEST SWAP3 POP POP PUSH1 0x60 DUP7 ADD MLOAD SWAP3 POP DUP1 DUP6 DUP4 SUB ADD PUSH1 0x80 DUP7 ADD MSTORE POP PUSH2 0x14A8 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST SWAP6 SWAP5 POP POP POP POP POP JUMP JUMPDEST SWAP1 MLOAD MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE DUP3 MLOAD PUSH1 0x40 PUSH1 0x20 DUP5 ADD MSTORE PUSH2 0x14D8 PUSH1 0x60 DUP5 ADD DUP3 PUSH2 0x10EE JUMP JUMPDEST PUSH1 0x20 DUP6 ADD MLOAD SWAP2 POP PUSH32 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 DUP5 DUP3 SUB ADD PUSH1 0x40 DUP6 ADD MSTORE PUSH2 0x14A8 DUP2 DUP4 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x0 PUSH1 0x20 DUP3 MSTORE PUSH2 0x12E4 PUSH1 0x20 DUP4 ADD DUP5 PUSH2 0x10EE JUMP JUMPDEST SWAP1 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 DUP4 DUP3 MSTORE PUSH1 0x40 PUSH1 0x20 DUP4 ADD MSTORE PUSH2 0xE49 PUSH1 0x40 DUP4 ADD DUP5 PUSH2 0x10A4 JUMP JUMPDEST PUSH1 0x40 MLOAD DUP2 DUP2 ADD PUSH8 0xFFFFFFFFFFFFFFFF DUP2 GT DUP3 DUP3 LT OR ISZERO PUSH2 0x1567 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x40 MSTORE SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 PUSH8 0xFFFFFFFFFFFFFFFF DUP3 GT ISZERO PUSH2 0x1585 JUMPI DUP1 DUP2 REVERT JUMPDEST POP PUSH1 0x20 SWAP1 DUP2 MUL ADD SWAP1 JUMP JUMPDEST PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0x15AA JUMPI DUP2 DUP2 ADD MLOAD DUP4 DUP3 ADD MSTORE PUSH1 0x20 ADD PUSH2 0x1592 JUMP JUMPDEST DUP4 DUP2 GT ISZERO PUSH2 0x15B9 JUMPI PUSH1 0x0 DUP5 DUP5 ADD MSTORE JUMPDEST POP POP POP POP JUMP JUMPDEST PUSH20 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF DUP2 AND DUP2 EQ PUSH2 0x433 JUMPI PUSH1 0x0 DUP1 REVERT INVALID LOG3 PUSH6 0x627A7A723158 KECCAK256 0xD4 SWAP6 GASPRICE STATICCALL DUP16 0xE2 PUSH24 0xA67A582A705EC911D7C404B5A84176AB0E36AA14DA0E5986 ORIGIN PUSH13 0x6578706572696D656E74616CF5 PUSH5 0x736F6C6343 STOP SDIV LT STOP BLOCKHASH ", + "sourceMap": "641:6913:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;641:6913:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1496:107;;;:::i;:::-;;3110:63;;;;;;;;;:::i;6518:128::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;5127:84;;;;;;;;;:::i;7141:345::-;;;;;;;;;:::i;:::-;;;;;;;;;;2288:334;;;;;;;;;:::i;:::-;;;;;;;;2948:52;;;;;;;6123:117;;;:::i;1389:101::-;;;:::i;1286:97::-;;;:::i;4480:153::-;;;:::i;:::-;;;;;;;;4212:73;;;:::i;:::-;;;;;;;;1609:111;;;:::i;2776:166::-;;;;;;;;;:::i;3319:52::-;;;;;;;4659:72;;;:::i;3894:70::-;;;;;;;6719:317;;;;;;;;;:::i;:::-;;;;;;;;5932:112;;;:::i;989:140::-;;;;;;;;;:::i;4736:69::-;;;:::i;862:121::-;;;:::i;4143:64::-;;;;;;;4811:134;;;:::i;:::-;;;;;;;;;3809:80;;;:::i;:::-;;;;;;;;5277:125;;;:::i;3453:350::-;;;:::i;:::-;;;;;;;;1135:145;;;:::i;3969:79::-;;;;;;;6319:123;;;;;;;;;:::i;4951:47::-;;;;;;;1496:107;1564:32;;;;;;;;;;;;;;;;;;;;1496:107::o;3110:63::-;;:::o;6518:128::-;-1:-1:-1;6635:4:0;;6518:128::o;5127:84::-;5188:10;5177:27;;;5200:3;5177:27;;;;;;;;;;;;;;;5127:84;:::o;7141:345::-;-1:-1:-1;;7388:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7141:345:0:o;2288:334::-;2399:21;2436:19;:56;;;;;;;;;;;;;;;;;;;2502:20;2552:6;2560:4;2535:30;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;2535:30:0;;;2525:41;;;;;;2502:64;;2583:32;2593:12;2607:1;2610;2613;2583:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;2583:32:0;;;;;;2288:334;-1:-1:-1;;;;;;;;2288:334:0:o;6123:117::-;6229:4;6123:117;;:::o;1389:101::-;1469:13;;;;;;;;;;;;;;;;1462:21;;;;;;;1469:13;1462:21;;;;1286:97;1353:23;;;;;;;;;;;4480:153;4574:51;;:::i;4212:73::-;4262:19;;:::i;1609:111::-;1698:14;;;;;;;;;;;;;;;;1683:30;;;;;;;1698:14;1683:30;;;;2776:166;-1:-1:-1;2934:1:0;;2776:166;-1:-1:-1;;;2776:166:0:o;4659:72::-;4699:4;4714:14;;4727:1;4714:14;;;;;4659:72;:::o;6719:317::-;6833:20;;:::i;:::-;-1:-1:-1;6876:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6719:317::o;5932:112::-;6016:21;;989:140;1117:1;:5;;989:140::o;4736:69::-;4788:9;:14;;4801:1;4788:14;;;4736:69::o;862:121::-;975:1;862:121;:::o;4811:134::-;4919:19;;;;;;;;;;;;;;;;;4927:1;4811:134;:::o;3809:80::-;3870:15;3809:80;:::o;5277:125::-;5326:69;;;;;;;;;;;;;;;5277:125::o;3453:350::-;3497:15;;:::i;:::-;3551:14;;;3563:1;3551:14;;;3524:24;3551:14;;;;;;;;;;;;;;;;;;;;;;;;;;3524:41;;3575:22;;;;;;;;;;;;;;;;;:9;3585:1;3575:12;;;;;;;;;;;;;:22;;;;3607;;;;;;;;;;;;;;;;;:9;3617:1;3607:12;;;;;;;;;;;;;;;;;;:22;;;;3647:149;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;3647:149:0;;;;-1:-1:-1;3453:350:0;:::o;1135:145::-;711:4;1135:145;:::o;641:6913::-;;;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o;1002:685:-1:-;;1120:3;1113:4;1105:6;1101:17;1097:27;1087:2;;-1:-1;;1128:12;1087:2;1175:6;1162:20;1197:81;1212:65;1270:6;1212:65;;;1197:81;;;1306:21;;;1188:90;-1:-1;1350:4;1363:14;;;;1338:17;;1458:1;1443:238;1468:6;1465:1;1462:13;1443:238;;;1575:42;1613:3;1350:4;1551:3;1538:17;1342:6;1526:30;;1575:42;;;1563:55;;1350:4;1632:14;;;;1660;;;;;1490:1;1483:9;1443:238;;;1447:14;;;;1080:607;;;;;2448:727;;2580:3;2573:4;2565:6;2561:17;2557:27;2547:2;;-1:-1;;2588:12;2547:2;2635:6;2622:20;2657:95;2672:79;2744:6;2672:79;;2657:95;2780:21;;;2648:104;-1:-1;2824:4;2837:14;;;;2812:17;;2932:1;2917:252;2942:6;2939:1;2936:13;2917:252;;;3049:56;3101:3;2824:4;3025:3;3012:17;2816:6;3000:30;;3049:56;;;3037:69;;2824:4;3120:14;;;;3148;;;;;2964:1;2957:9;2917:252;;4100:432;;4197:3;4190:4;4182:6;4178:17;4174:27;4164:2;;-1:-1;;4205:12;4164:2;4252:6;4239:20;37223:18;37215:6;37212:30;37209:2;;;-1:-1;;37245:12;37209:2;4274:60;37386:4;37318:9;4190:4;37303:6;37299:17;37295:33;37376:15;4274:60;;;4265:69;;4354:6;4347:5;4340:21;4458:3;37386:4;4449:6;4382;4440:16;;4437:25;4434:2;;;4475:1;;4465:12;4434:2;41724:6;37386:4;4382:6;4378:17;37386:4;4416:5;4412:16;41701:30;41780:1;41762:16;;;37386:4;41762:16;41755:27;4416:5;4157:375;-1:-1;;4157:375;7617:1072;;7725:4;7713:9;7708:3;7704:19;7700:30;7697:2;;;-1:-1;;7733:12;7697:2;7761:20;7725:4;7761:20;;;7752:29;;7849:17;7836:31;7887:18;;7879:6;7876:30;7873:2;;;7864:1;;7909:12;7873:2;7954:54;8004:3;7995:6;7984:9;7980:22;7954:54;;;7936:16;7929:80;8108:48;8152:3;8075:2;8132:9;8128:22;8108:48;;;8075:2;8094:5;8090:16;8083:74;8262:2;8251:9;8247:18;8234:32;8220:46;;7887:18;8278:6;8275:30;8272:2;;;7864:1;;8308:12;8272:2;8353:75;8424:3;8415:6;8404:9;8400:22;8353:75;;;8262:2;8339:5;8335:16;8328:101;8521:2;8510:9;8506:18;8493:32;8479:46;;7887:18;8537:6;8534:30;8531:2;;;7864:1;;8567:12;8531:2;;8612:55;8663:3;8654:6;8643:9;8639:22;8612:55;;;8521:2;8598:5;8594:16;8587:81;;7691:998;;;;;9948:128;10014:20;;41531:10;41520:22;;42811:34;;42801:2;;42859:1;;42849:12;42801:2;9999:77;;;;;10216:743;;;;;;10388:3;10376:9;10367:7;10363:23;10359:33;10356:2;;;-1:-1;;10395:12;10356:2;85:6;72:20;97:33;124:5;97:33;;;10447:63;-1:-1;10547:2;10586:22;;9878:20;;-1:-1;10655:2;10694:22;;9878:20;;-1:-1;10763:2;10802:22;;72:20;97:33;72:20;97:33;;;10350:609;;;;-1:-1;10350:609;;10871:3;10911:22;9878:20;;10350:609;-1:-1;;10350:609;10966:457;;11135:2;;11123:9;11114:7;11110:23;11106:32;11103:2;;;-1:-1;;11141:12;11103:2;11199:17;11186:31;11237:18;11229:6;11226:30;11223:2;;;-1:-1;;11259:12;11223:2;11390:6;11379:9;11375:22;337:3;330:4;322:6;318:17;314:27;304:2;;-1:-1;;345:12;304:2;392:6;379:20;365:34;;414:120;429:104;526:6;429:104;;414:120;562:21;;;619:14;;;;594:17;;;-1:-1;699:273;724:6;721:1;718:13;699:273;;;831:77;904:3;11135:2;807:3;794:17;598:6;782:30;;831:77;;;819:90;;923:14;;;;951;;;;746:1;739:9;699:273;;;-1:-1;11279:128;;11097:326;-1:-1;;;;;;;;11097:326;11430:387;;11564:2;;11552:9;11543:7;11539:23;11535:32;11532:2;;;-1:-1;;11570:12;11532:2;11628:17;11615:31;11666:18;11658:6;11655:30;11652:2;;;-1:-1;;11688:12;11652:2;11784:6;11773:9;11769:22;1833:3;1826:4;1818:6;1814:17;1810:27;1800:2;;-1:-1;;1841:12;1800:2;1888:6;1875:20;1861:34;;1910:85;1925:69;1987:6;1925:69;;1910:85;2023:21;;;2080:14;;;;2055:17;;;-1:-1;2160:238;2185:6;2182:1;2179:13;2160:238;;;2292:42;2330:3;11564:2;2268:3;2255:17;2059:6;2243:30;;2292:42;;;2280:55;;2349:14;;;;2377;;;;2207:1;2200:9;2160:238;;11824:415;;11972:2;11960:9;11951:7;11947:23;11943:32;11940:2;;;-1:-1;;11978:12;11940:2;12036:17;12023:31;12074:18;12066:6;12063:30;12060:2;;;-1:-1;;12096:12;12060:2;12126:97;12215:7;12206:6;12195:9;12191:22;12126:97;;;12116:107;11934:305;-1:-1;;;;11934:305;12246:613;;;;;12399:3;12387:9;12378:7;12374:23;12370:33;12367:2;;;-1:-1;;12406:12;12367:2;4042:6;4029:20;12458:63;;12558:2;12599:9;12595:22;10148:20;41625:4;42958:5;41614:16;42935:5;42932:33;42922:2;;-1:-1;;42969:12;42922:2;12361:498;;12566:61;;-1:-1;;;;12664:2;12703:22;;4029:20;;12772:2;12811:22;4029:20;;12361:498;12866:345;;12979:2;12967:9;12958:7;12954:23;12950:32;12947:2;;;-1:-1;;12985:12;12947:2;13043:17;13030:31;13081:18;13073:6;13070:30;13067:2;;;-1:-1;;13103:12;13067:2;13133:62;13187:7;13178:6;13167:9;13163:22;13133:62;;13218:239;;13321:2;13309:9;13300:7;13296:23;13292:32;13289:2;;;-1:-1;;13327:12;13289:2;-1:-1;5055:20;;13283:174;-1:-1;13283:174;13818:385;;13951:2;13939:9;13930:7;13926:23;13922:32;13919:2;;;-1:-1;;13957:12;13919:2;14015:17;14002:31;14053:18;;14045:6;14042:30;14039:2;;;-1:-1;;14075:12;14039:2;14170:6;14159:9;14155:22;6174:4;6162:9;6157:3;6153:19;6149:30;6146:2;;;-1:-1;;6182:12;6146:2;6210:20;6174:4;6210:20;;;6201:29;;9891:6;9878:20;6293:16;6286:75;13951:2;6438:9;6434:18;6421:32;14053:18;6465:6;6462:30;6459:2;;;-1:-1;;6495:12;6459:2;6540:54;6590:3;6581:6;6570:9;6566:22;6540:54;;;13951:2;6526:5;6522:16;6515:80;;6683:2;6672:9;6668:18;6655:32;14053:18;6699:6;6696:30;6693:2;;;-1:-1;;6729:12;6693:2;6774:55;6825:3;6816:6;6805:9;6801:22;6774:55;;;6683:2;6756:16;;6749:81;-1:-1;6760:5;;13913:290;-1:-1;;;;;13913:290;14210:385;;14343:2;14331:9;14322:7;14318:23;14314:32;14311:2;;;-1:-1;;14349:12;14311:2;14407:17;14394:31;14445:18;;14437:6;14434:30;14431:2;;;-1:-1;;14467:12;14431:2;14562:6;14551:9;14547:22;7014:4;7002:9;6997:3;6993:19;6989:30;6986:2;;;-1:-1;;7022:12;6986:2;7050:20;7014:4;7050:20;;;7041:29;;7140:17;7127:31;14445:18;7170:6;7167:30;7164:2;;;-1:-1;;7200:12;7164:2;7245:68;7309:3;7300:6;7289:9;7285:22;7245:68;;;7227:16;7220:94;;14343:2;7399:9;7395:18;7382:32;14445:18;7426:6;7423:30;7420:2;;;-1:-1;;7456:12;7420:2;7501:55;7552:3;7543:6;7532:9;7528:22;7501:55;;;14343:2;7483:16;;7476:81;-1:-1;7487:5;;14305:290;-1:-1;;;;;14305:290;14602:373;;14729:2;14717:9;14708:7;14704:23;14700:32;14697:2;;;-1:-1;;14735:12;14697:2;14793:17;14780:31;14831:18;14823:6;14820:30;14817:2;;;-1:-1;;14853:12;14817:2;14883:76;14951:7;14942:6;14931:9;14927:22;14883:76;;15230:701;;;;15387:2;15375:9;15366:7;15362:23;15358:32;15355:2;;;-1:-1;;15393:12;15355:2;9891:6;9878:20;15445:63;;15573:2;15562:9;15558:18;15545:32;15597:18;;15589:6;15586:30;15583:2;;;-1:-1;;15619:12;15583:2;15649:62;15703:7;15694:6;15683:9;15679:22;15649:62;;;15639:72;;15776:2;15765:9;15761:18;15748:32;15734:46;;15597:18;15792:6;15789:30;15786:2;;;-1:-1;;15822:12;15786:2;;15852:63;15907:7;15898:6;15887:9;15883:22;15852:63;;;15842:73;;;15349:582;;;;;;18727:343;;18869:5;38830:12;39916:6;39911:3;39904:19;18962:52;19007:6;39953:4;39948:3;39944:14;39953:4;18988:5;18984:16;18962:52;;;42242:2;42222:14;42238:7;42218:28;19026:39;;;;39953:4;19026:39;;18817:253;-1:-1;;18817:253;26122:1080;;26346:16;26340:23;26269:4;26383:14;26376:38;26429:67;26269:4;26264:3;26260:14;26477:12;26429:67;;;26586:4;;;41531:10;26586:4;26579:5;26575:16;26569:23;41520:22;26586:4;26648:3;26644:14;28632:36;26754:4;26747:5;26743:16;26737:23;26806:3;26800:4;26796:14;26754:4;26784:3;26780:14;26773:38;26826:109;16703:5;38830:12;39916:6;39911:3;39904:19;26586:4;39948:3;39944:14;16715:88;;26586:4;;16860:6;16856:17;39948:3;16847:27;;26586:4;16946:5;38506:14;-1:-1;16991:10;;16985:341;17010:6;17007:1;17004:13;16985:341;;;17062:20;39948:3;17066:4;17062:20;;17057:3;17050:33;16050:60;16106:3;17117:6;17111:13;16050:60;;;17032:1;17025:9;;;;;17305:14;;;;17131:82;-1:-1;39630:14;;16985:341;;;16989:14;27023:4;27016:5;27012:16;27006:23;26986:43;;27075:3;27069:4;27065:14;27023:4;27053:3;27049:14;27042:38;27095:69;27159:4;27145:12;27095:69;;;27186:11;26242:960;-1:-1;;;;;;;;;26242:960;28794:401;;19237:5;38830:12;19348:52;19393:6;19388:3;19381:4;19374:5;19370:16;19348:52;;;19412:16;;;;18519:37;;;-1:-1;19381:4;29158:12;;28947:248;-1:-1;28947:248;29202:213;41325:42;41314:54;;;;16437:37;;29320:2;29305:18;;29291:124;29422:437;;29628:2;;29617:9;29613:18;29628:2;29649:17;29642:47;29703:146;17690:5;38830:12;39916:6;39911:3;39904:19;39944:14;29617:9;39944:14;17702:112;;39944:14;29628:2;17871:6;17867:17;29617:9;17858:27;;17846:39;;29628:2;17975:5;38506:14;-1:-1;18014:387;18039:6;18036:1;18033:13;18014:387;;;18091:20;29617:9;18095:4;18091:20;;18086:3;18079:33;16264:88;16348:3;18146:6;18140:13;16264:88;;;18160:110;-1:-1;18380:14;;;;39630;;;;18061:1;18054:9;18014:387;;;-1:-1;29695:154;;29599:260;-1:-1;;;;;;;29599:260;29866:539;18519:37;;;41625:4;41614:16;;;;30225:2;30210:18;;28747:35;30308:2;30293:18;;18519:37;30391:2;30376:18;;18519:37;30064:3;30049:19;;30035:370;30412:691;;30642:2;30663:17;30656:47;30717:76;30642:2;30631:9;30627:18;30779:6;30717:76;;;30841:9;30835:4;30831:20;30826:2;30815:9;30811:18;30804:48;30866:76;30937:4;30928:6;30866:76;;;30990:9;30984:4;30980:20;30975:2;30964:9;30960:18;30953:48;31015:78;31088:4;31079:6;31015:78;;;31007:86;30613:490;-1:-1;;;;;;;30613:490;31110:293;;31244:2;31265:17;31258:47;31319:74;31244:2;31233:9;31229:18;31379:6;31319:74;;;31311:82;31215:188;-1:-1;;;31215:188;31410:710;31701:2;31715:47;;;21324:1;31686:18;;;39904:19;21359:66;39944:14;;;21339:87;21445:12;39953:4;31924:18;;31917:48;;;21013:1;21445:12;;;39904:19;21048:7;39944:14;;;21028:28;21075:12;;;31672:448;32127:407;32318:2;32332:47;;;21696:2;32303:18;;;39904:19;21732:15;39944:14;;;21712:36;21767:12;;;32289:245;32541:407;32732:2;32746:47;;;22018:2;32717:18;;;39904:19;22054:16;39944:14;;;22034:37;22090:12;;;32703:245;32955:381;;33133:2;33154:17;33147:47;23287:16;23281:23;23214:4;33133:2;33122:9;33118:18;23317:38;22405:16;22399:23;23205:14;33122:9;23205:14;18519:37;33133:2;22562:5;22558:16;22552:23;22334:4;22595:14;33122:9;22595:14;22588:38;22641:67;22325:14;33122:9;22325:14;22689:12;22641:67;;;22792:4;22785:5;22781:16;22775:23;22755:43;;22834:14;33122:9;22838:4;22834:14;;22818;33122:9;22818:14;22811:38;22864:69;22928:4;22914:12;22864:69;;;22955:11;;;;33133:2;23556:5;23552:16;23546:23;23605:14;;33122:9;23609:4;23605:14;;22792:4;33122:9;23589:14;23582:38;23635:67;23697:4;23683:12;23635:67;;;22792:4;23781:5;23777:16;23771:23;23751:43;;23605:14;33122:9;23834:4;23830:14;;22334:4;33122:9;23814:14;23807:38;23860:67;23922:4;23908:12;23860:67;;;23852:75;;;22334:4;24006:5;24002:16;23996:23;23976:43;;23605:14;33122:9;24059:4;24055:14;;23214:4;33122:9;24039:14;24032:38;;24085:69;24149:4;24135:12;24085:69;;;33200:126;33104:232;-1:-1;;;;;33104:232;33343:453;24620:23;;25941;18519:37;;33581:2;33566:18;;33552:244;33803:377;;33979:2;34000:17;33993:47;25139:16;25133:23;25060:4;33979:2;33968:9;33964:18;25169:38;25222:95;25051:14;33968:9;25051:14;25298:12;25222:95;;;33979:2;25402:5;25398:16;25392:23;25372:43;;25451:14;33968:9;25455:4;25451:14;;25060:4;33968:9;25435:14;25428:38;25481:69;25545:4;25531:12;25481:69;;34187:353;;34351:2;34372:17;34365:47;34426:104;34351:2;34340:9;34336:18;34516:6;34426:104;;34547:213;18519:37;;;34665:2;34650:18;;34636:124;34767:412;;18549:5;18526:3;18519:37;34933:2;35051;35040:9;35036:18;35029:48;35091:78;34933:2;34922:9;34918:18;35155:6;35091:78;;35186:256;35248:2;35242:9;35274:17;;;35349:18;35334:34;;35370:22;;;35331:62;35328:2;;;35406:1;;35396:12;35328:2;35248;35415:22;35226:216;;-1:-1;35226:216;35449:344;;35648:18;35640:6;35637:30;35634:2;;;-1:-1;;35670:12;35634:2;-1:-1;35715:4;35703:17;;;35768:15;;35571:222;41797:268;41862:1;41869:101;41883:6;41880:1;41877:13;41869:101;;;41950:11;;;41944:18;41931:11;;;41924:39;41905:2;41898:10;41869:101;;;41985:6;41982:1;41979:13;41976:2;;;41862:1;42041:6;42036:3;42032:16;42025:27;41976:2;;41846:219;;;;42259:117;41325:42;42346:5;41314:54;42321:5;42318:35;42308:2;;42367:1;;42357:12" } } }, @@ -813,12 +887,12 @@ } }, "sourceCodes": { - "AbiGenDummy.sol": "/*\n\n Copyright 2019 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma experimental ABIEncoderV2;\n\npragma solidity ^0.5.5;\n\n\ncontract AbiGenDummy\n{\n\n uint256 constant internal SOME_CONSTANT = 1234;\n string constant internal REVERT_REASON = \"REVERT_WITH_CONSTANT\";\n string constant internal REQUIRE_REASON = \"REQUIRE_WITH_CONSTANT\";\n\n function simplePureFunction ()\n public\n pure\n returns (uint256 result)\n {\n return 1;\n }\n\n function simplePureFunctionWithInput (uint256 x)\n public\n pure\n returns (uint256 sum)\n {\n return 1 + x;\n }\n\n function pureFunctionWithConstant ()\n public\n pure\n returns (uint256 someConstant)\n {\n return SOME_CONSTANT;\n }\n\n function simpleRevert ()\n public\n pure\n {\n revert(\"SIMPLE_REVERT\");\n }\n\n function revertWithConstant ()\n public\n pure\n {\n revert(REVERT_REASON);\n }\n\n function simpleRequire ()\n public\n pure\n {\n require(0 > 1, \"SIMPLE_REQUIRE\");\n }\n\n function requireWithConstant ()\n public\n pure\n {\n require(0 > 1, REQUIRE_REASON);\n }\n\n /// @dev test that devdocs will be generated and\n /// that multiline devdocs will look okay\n /// @param hash description of some hash. Let's make this line super long to demonstrate hanging indents for method params. It has to be more than one hundred twenty columns.\n /// @param v some v, recovery id\n /// @param r ECDSA r output\n /// @param s ECDSA s output\n /// @return the signerAddress that created this signature. this line too is super long in order to demonstrate the proper hanging indentation in generated code.\n function ecrecoverFn(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n public\n pure\n returns (address signerAddress)\n {\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, hash));\n return ecrecover(prefixedHash, v, r, s);\n }\n\n // test: generated code should normalize address inputs to lowercase\n // add extra inputs to make sure it works with address in any position\n function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c)\n public\n pure\n returns (address z)\n {\n return x;\n }\n\n function acceptsBytes(bytes memory a) public pure {}\n\n /// @dev a method that accepts an array of bytes\n /// @param a the array of bytes being accepted\n function acceptsAnArrayOfBytes(bytes[] memory a) public pure {}\n\n struct Struct {\n bytes someBytes;\n uint32 anInteger;\n bytes[] aDynamicArrayOfBytes;\n string aString;\n }\n\n function structInput(Struct memory s) public pure {}\n\n /// @dev a method that returns a struct\n /// @return a Struct struct\n function structOutput() public pure returns(Struct memory s) {\n bytes[] memory byteArray = new bytes[](2);\n byteArray[0] = \"0x123\";\n byteArray[1] = \"0x321\";\n\n return Struct({\n someBytes: \"0x123\",\n anInteger: 5,\n aDynamicArrayOfBytes: byteArray,\n aString: \"abc\"\n });\n }\n\n function methodReturningArrayOfStructs() public pure returns(Struct[] memory) {}\n\n struct NestedStruct {\n Struct innerStruct;\n string description;\n }\n\n function nestedStructInput(NestedStruct memory n) public pure {}\n function nestedStructOutput() public pure returns(NestedStruct memory) {}\n\n struct StructNotDirectlyUsedAnywhere {\n uint256 aField;\n }\n\n struct NestedStructWithInnerStructNotUsedElsewhere {\n StructNotDirectlyUsedAnywhere innerStruct;\n }\n\n function methodUsingNestedStructWithInnerStructNotUsedElsewhere()\n public pure returns(NestedStructWithInnerStructNotUsedElsewhere memory)\n {}\n\n uint someState;\n function nonPureMethod() public returns(uint) { return someState += 1; }\n function nonPureMethodThatReturnsNothing() public { someState += 1; }\n\n function methodReturningMultipleValues()\n public pure returns (uint256, string memory)\n {\n return (1, \"hello\");\n }\n\n function overloadedMethod(int a) public pure {}\n function overloadedMethod(string memory a) public pure {}\n\n\n event Withdrawal(address indexed _owner, uint _value);\n\n function withdraw(uint wad) public {\n emit Withdrawal(msg.sender, wad);\n }\n\n event SimpleEvent(bytes someBytes, string someString);\n\n function emitSimpleEvent() public {\n emit SimpleEvent(\n hex'12345678',\n \"lorem\"\n );\n }\n\n // begin tests for `decodeTransactionData`, `decodeReturnData`\n /// @dev complex input is dynamic and more difficult to decode than simple input.\n struct ComplexInput {\n uint256 foo;\n bytes bar;\n string car;\n }\n\n /// @dev complex input is dynamic and more difficult to decode than simple input.\n struct ComplexOutput {\n ComplexInput input;\n bytes lorem;\n bytes ipsum;\n string dolor;\n }\n\n /// @dev Tests decoding when both input and output are empty.\n function noInputNoOutput()\n public\n pure\n {\n // NOP\n require(true == true);\n }\n\n /// @dev Tests decoding when input is empty and output is non-empty.\n function noInputSimpleOutput()\n public\n pure\n returns (uint256)\n {\n return 1991;\n }\n\n /// @dev Tests decoding when input is not empty but output is empty.\n function simpleInputNoOutput(uint256)\n public\n pure\n {\n // NOP\n require(true == true);\n }\n\n /// @dev Tests decoding when both input and output are non-empty.\n function simpleInputSimpleOutput(uint256)\n public\n pure\n returns (uint256)\n {\n return 1991;\n }\n\n /// @dev Tests decoding when the input and output are complex.\n function complexInputComplexOutput(ComplexInput memory complexInput)\n public\n pure\n returns (ComplexOutput memory)\n {\n return ComplexOutput({\n input: complexInput,\n lorem: hex'12345678',\n ipsum: hex'87654321',\n dolor: \"amet\"\n });\n }\n\n /// @dev Tests decoding when the input and output are complex and have more than one argument.\n function multiInputMultiOutput(\n uint256,\n bytes memory,\n string memory\n )\n public\n pure\n returns (\n bytes memory,\n bytes memory,\n string memory\n )\n {\n return (\n hex'12345678',\n hex'87654321',\n \"amet\"\n );\n }\n\n // end tests for `decodeTransactionData`, `decodeReturnData`\n}\n" + "AbiGenDummy.sol": "/*\n\n Copyright 2019 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n\npragma experimental ABIEncoderV2;\n\npragma solidity ^0.5.5;\n\n\ncontract AbiGenDummy\n{\n\n uint256 constant internal SOME_CONSTANT = 1234;\n string constant internal REVERT_REASON = \"REVERT_WITH_CONSTANT\";\n string constant internal REQUIRE_REASON = \"REQUIRE_WITH_CONSTANT\";\n\n function simplePureFunction ()\n public\n pure\n returns (uint256 result)\n {\n return 1;\n }\n\n function simplePureFunctionWithInput (uint256 x)\n public\n pure\n returns (uint256 sum)\n {\n return 1 + x;\n }\n\n function pureFunctionWithConstant ()\n public\n pure\n returns (uint256 someConstant)\n {\n return SOME_CONSTANT;\n }\n\n function simpleRevert ()\n public\n pure\n {\n revert(\"SIMPLE_REVERT\");\n }\n\n function revertWithConstant ()\n public\n pure\n {\n revert(REVERT_REASON);\n }\n\n function simpleRequire ()\n public\n pure\n {\n require(0 > 1, \"SIMPLE_REQUIRE\");\n }\n\n function requireWithConstant ()\n public\n pure\n {\n require(0 > 1, REQUIRE_REASON);\n }\n\n /// @dev test that devdocs will be generated and\n /// that multiline devdocs will look okay\n /// @param hash description of some hash. Let's make this line super long to demonstrate hanging indents for method params. It has to be more than one hundred twenty columns.\n /// @param v some v, recovery id\n /// @param r ECDSA r output\n /// @param s ECDSA s output\n /// @return the signerAddress that created this signature. this line too is super long in order to demonstrate the proper hanging indentation in generated code.\n function ecrecoverFn(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n public\n pure\n returns (address signerAddress)\n {\n bytes memory prefix = \"\\x19Ethereum Signed Message:\\n32\";\n bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, hash));\n return ecrecover(prefixedHash, v, r, s);\n }\n\n // test: generated code should normalize address inputs to lowercase\n // add extra inputs to make sure it works with address in any position\n function withAddressInput(address x, uint256 a, uint256 b, address y, uint256 c)\n public\n pure\n returns (address z)\n {\n return x;\n }\n\n function acceptsBytes(bytes memory a) public pure {}\n\n /// @dev a method that accepts an array of bytes\n /// @param a the array of bytes being accepted\n function acceptsAnArrayOfBytes(bytes[] memory a) public pure {}\n\n struct Struct {\n bytes someBytes;\n uint32 anInteger;\n bytes[] aDynamicArrayOfBytes;\n string aString;\n }\n\n function structInput(Struct memory s) public pure {}\n\n /// @dev a method that returns a struct\n /// @return a Struct struct\n function structOutput() public pure returns(Struct memory s) {\n bytes[] memory byteArray = new bytes[](2);\n byteArray[0] = \"0x123\";\n byteArray[1] = \"0x321\";\n\n return Struct({\n someBytes: \"0x123\",\n anInteger: 5,\n aDynamicArrayOfBytes: byteArray,\n aString: \"abc\"\n });\n }\n\n function methodReturningArrayOfStructs() public pure returns(Struct[] memory) {}\n function methodAcceptingArrayOfStructs(Struct[] memory) public pure {}\n function methodAcceptingArrayOfArrayOfStructs(Struct[][] memory) public pure {}\n\n struct NestedStruct {\n Struct innerStruct;\n string description;\n }\n\n function nestedStructInput(NestedStruct memory n) public pure {}\n function nestedStructOutput() public pure returns(NestedStruct memory) {}\n\n struct StructNotDirectlyUsedAnywhere {\n uint256 aField;\n }\n\n struct NestedStructWithInnerStructNotUsedElsewhere {\n StructNotDirectlyUsedAnywhere innerStruct;\n }\n\n function methodUsingNestedStructWithInnerStructNotUsedElsewhere()\n public pure returns(NestedStructWithInnerStructNotUsedElsewhere memory)\n {}\n\n uint someState;\n function nonPureMethod() public returns(uint) { return someState += 1; }\n function nonPureMethodThatReturnsNothing() public { someState += 1; }\n\n function methodReturningMultipleValues()\n public pure returns (uint256, string memory)\n {\n return (1, \"hello\");\n }\n\n function overloadedMethod(int a) public pure {}\n function overloadedMethod(string memory a) public pure {}\n\n\n event Withdrawal(address indexed _owner, uint _value);\n\n function withdraw(uint wad) public {\n emit Withdrawal(msg.sender, wad);\n }\n\n event SimpleEvent(bytes someBytes, string someString);\n\n function emitSimpleEvent() public {\n emit SimpleEvent(\n hex'12345678',\n \"lorem\"\n );\n }\n\n // begin tests for `decodeTransactionData`, `decodeReturnData`\n /// @dev complex input is dynamic and more difficult to decode than simple input.\n struct ComplexInput {\n uint256 foo;\n bytes bar;\n string car;\n }\n\n /// @dev complex input is dynamic and more difficult to decode than simple input.\n struct ComplexOutput {\n ComplexInput input;\n bytes lorem;\n bytes ipsum;\n string dolor;\n }\n\n /// @dev Tests decoding when both input and output are empty.\n function noInputNoOutput()\n public\n pure\n {\n // NOP\n require(true == true);\n }\n\n /// @dev Tests decoding when input is empty and output is non-empty.\n function noInputSimpleOutput()\n public\n pure\n returns (uint256)\n {\n return 1991;\n }\n\n /// @dev Tests decoding when input is not empty but output is empty.\n function simpleInputNoOutput(uint256)\n public\n pure\n {\n // NOP\n require(true == true);\n }\n\n /// @dev Tests decoding when both input and output are non-empty.\n function simpleInputSimpleOutput(uint256)\n public\n pure\n returns (uint256)\n {\n return 1991;\n }\n\n /// @dev Tests decoding when the input and output are complex.\n function complexInputComplexOutput(ComplexInput memory complexInput)\n public\n pure\n returns (ComplexOutput memory)\n {\n return ComplexOutput({\n input: complexInput,\n lorem: hex'12345678',\n ipsum: hex'87654321',\n dolor: \"amet\"\n });\n }\n\n /// @dev Tests decoding when the input and output are complex and have more than one argument.\n function multiInputMultiOutput(\n uint256,\n bytes memory,\n string memory\n )\n public\n pure\n returns (\n bytes memory,\n bytes memory,\n string memory\n )\n {\n return (\n hex'12345678',\n hex'87654321',\n \"amet\"\n );\n }\n\n // end tests for `decodeTransactionData`, `decodeReturnData`\n}\n" }, - "sourceTreeHashHex": "0xe85eeae56e9951f6082d8885c3b93cdfd91334f45394bd3e841a28cfe287062c", + "sourceTreeHashHex": "0x7eddc853f5154dd78fdcb2634f515f9e86c0e5ef161f4bc24455e92bb7b874f4", "compiler": { "name": "solc", - "version": "soljson-v0.5.12+commit.7709ece9.js", + "version": "soljson-v0.5.16+commit.9c3226ce.js", "settings": { "optimizer": { "enabled": true, diff --git a/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol b/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol index ed867231f7..20f897023a 100644 --- a/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol +++ b/packages/abi-gen/test-cli/fixtures/contracts/AbiGenDummy.sol @@ -138,6 +138,8 @@ contract AbiGenDummy } function methodReturningArrayOfStructs() public pure returns(Struct[] memory) {} + function methodAcceptingArrayOfStructs(Struct[] memory) public pure {} + function methodAcceptingArrayOfArrayOfStructs(Struct[][] memory) public pure {} struct NestedStruct { Struct innerStruct; diff --git a/packages/abi-gen/test-cli/output/python/abi_gen_dummy/__init__.py b/packages/abi-gen/test-cli/output/python/abi_gen_dummy/__init__.py index f5ad70668c..866128d746 100644 --- a/packages/abi-gen/test-cli/output/python/abi_gen_dummy/__init__.py +++ b/packages/abi-gen/test-cli/output/python/abi_gen_dummy/__init__.py @@ -457,6 +457,108 @@ class EmitSimpleEventMethod(ContractMethod): return self._underlying_method().estimateGas(tx_params.as_dict()) +class MethodAcceptingArrayOfArrayOfStructsMethod(ContractMethod): + """Various interfaces to the methodAcceptingArrayOfArrayOfStructs method.""" + + def __init__( + self, + web3_or_provider: Union[Web3, BaseProvider], + contract_address: str, + contract_function: ContractFunction, + validator: Validator = None, + ): + """Persist instance data.""" + super().__init__(web3_or_provider, contract_address, validator) + self._underlying_method = contract_function + + def validate_and_normalize_inputs( + self, index_0: List[List[AbiGenDummyStruct]] + ): + """Validate the inputs to the methodAcceptingArrayOfArrayOfStructs method.""" + self.validator.assert_valid( + method_name="methodAcceptingArrayOfArrayOfStructs", + parameter_name="index_0", + argument_value=index_0, + ) + return index_0 + + def call( + self, + index_0: List[List[AbiGenDummyStruct]], + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying contract method via eth_call. + + :param tx_params: transaction parameters + + """ + (index_0) = self.validate_and_normalize_inputs(index_0) + tx_params = super().normalize_tx_params(tx_params) + self._underlying_method(index_0).call(tx_params.as_dict()) + + def estimate_gas( + self, + index_0: List[List[AbiGenDummyStruct]], + tx_params: Optional[TxParams] = None, + ) -> int: + """Estimate gas consumption of method call.""" + (index_0) = self.validate_and_normalize_inputs(index_0) + tx_params = super().normalize_tx_params(tx_params) + return self._underlying_method(index_0).estimateGas( + tx_params.as_dict() + ) + + +class MethodAcceptingArrayOfStructsMethod(ContractMethod): + """Various interfaces to the methodAcceptingArrayOfStructs method.""" + + def __init__( + self, + web3_or_provider: Union[Web3, BaseProvider], + contract_address: str, + contract_function: ContractFunction, + validator: Validator = None, + ): + """Persist instance data.""" + super().__init__(web3_or_provider, contract_address, validator) + self._underlying_method = contract_function + + def validate_and_normalize_inputs(self, index_0: List[AbiGenDummyStruct]): + """Validate the inputs to the methodAcceptingArrayOfStructs method.""" + self.validator.assert_valid( + method_name="methodAcceptingArrayOfStructs", + parameter_name="index_0", + argument_value=index_0, + ) + return index_0 + + def call( + self, + index_0: List[AbiGenDummyStruct], + tx_params: Optional[TxParams] = None, + ) -> None: + """Execute underlying contract method via eth_call. + + :param tx_params: transaction parameters + + """ + (index_0) = self.validate_and_normalize_inputs(index_0) + tx_params = super().normalize_tx_params(tx_params) + self._underlying_method(index_0).call(tx_params.as_dict()) + + def estimate_gas( + self, + index_0: List[AbiGenDummyStruct], + tx_params: Optional[TxParams] = None, + ) -> int: + """Estimate gas consumption of method call.""" + (index_0) = self.validate_and_normalize_inputs(index_0) + tx_params = super().normalize_tx_params(tx_params) + return self._underlying_method(index_0).estimateGas( + tx_params.as_dict() + ) + + class MethodReturningArrayOfStructsMethod(ContractMethod): """Various interfaces to the methodReturningArrayOfStructs method.""" @@ -1531,6 +1633,16 @@ class AbiGenDummy: :class:`EmitSimpleEventMethod`. """ + method_accepting_array_of_array_of_structs: MethodAcceptingArrayOfArrayOfStructsMethod + """Constructor-initialized instance of + :class:`MethodAcceptingArrayOfArrayOfStructsMethod`. + """ + + method_accepting_array_of_structs: MethodAcceptingArrayOfStructsMethod + """Constructor-initialized instance of + :class:`MethodAcceptingArrayOfStructsMethod`. + """ + method_returning_array_of_structs: MethodReturningArrayOfStructsMethod """Constructor-initialized instance of :class:`MethodReturningArrayOfStructsMethod`. @@ -1745,6 +1857,20 @@ class AbiGenDummy: web3_or_provider, contract_address, functions.emitSimpleEvent ) + self.method_accepting_array_of_array_of_structs = MethodAcceptingArrayOfArrayOfStructsMethod( + web3_or_provider, + contract_address, + functions.methodAcceptingArrayOfArrayOfStructs, + validator, + ) + + self.method_accepting_array_of_structs = MethodAcceptingArrayOfStructsMethod( + web3_or_provider, + contract_address, + functions.methodAcceptingArrayOfStructs, + validator, + ) + self.method_returning_array_of_structs = MethodReturningArrayOfStructsMethod( web3_or_provider, contract_address, @@ -1920,7 +2046,7 @@ class AbiGenDummy: def abi(): """Return the ABI to the underlying contract.""" return json.loads( - '[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"someBytes","type":"bytes"},{"indexed":false,"internalType":"string","name":"someString","type":"string"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes[]","name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"foo","type":"uint256"},{"internalType":"bytes","name":"bar","type":"bytes"},{"internalType":"string","name":"car","type":"string"}],"internalType":"struct AbiGenDummy.ComplexInput","name":"complexInput","type":"tuple"}],"name":"complexInputComplexOutput","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"foo","type":"uint256"},{"internalType":"bytes","name":"bar","type":"bytes"},{"internalType":"string","name":"car","type":"string"}],"internalType":"struct AbiGenDummy.ComplexInput","name":"input","type":"tuple"},{"internalType":"bytes","name":"lorem","type":"bytes"},{"internalType":"bytes","name":"ipsum","type":"bytes"},{"internalType":"string","name":"dolor","type":"string"}],"internalType":"struct AbiGenDummy.ComplexOutput","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"internalType":"address","name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"emitSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"methodReturningArrayOfStructs","outputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"methodReturningMultipleValues","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"methodUsingNestedStructWithInnerStructNotUsedElsewhere","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"aField","type":"uint256"}],"internalType":"struct AbiGenDummy.StructNotDirectlyUsedAnywhere","name":"innerStruct","type":"tuple"}],"internalType":"struct AbiGenDummy.NestedStructWithInnerStructNotUsedElsewhere","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"},{"internalType":"bytes","name":"index_1","type":"bytes"},{"internalType":"string","name":"index_2","type":"string"}],"name":"multiInputMultiOutput","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"innerStruct","type":"tuple"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct AbiGenDummy.NestedStruct","name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"innerStruct","type":"tuple"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct AbiGenDummy.NestedStruct","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"noInputNoOutput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"noInputSimpleOutput","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"a","type":"string"}],"name":"overloadedMethod","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"int256","name":"a","type":"int256"}],"name":"overloadedMethod","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"internalType":"uint256","name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"}],"name":"simpleInputNoOutput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"}],"name":"simpleInputSimpleOutput","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"x","type":"address"},{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"address","name":"y","type":"address"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"internalType":"address","name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]' # noqa: E501 (line-too-long) + '[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"someBytes","type":"bytes"},{"indexed":false,"internalType":"string","name":"someString","type":"string"}],"name":"SimpleEvent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"constant":true,"inputs":[{"internalType":"bytes[]","name":"a","type":"bytes[]"}],"name":"acceptsAnArrayOfBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"a","type":"bytes"}],"name":"acceptsBytes","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"uint256","name":"foo","type":"uint256"},{"internalType":"bytes","name":"bar","type":"bytes"},{"internalType":"string","name":"car","type":"string"}],"internalType":"struct AbiGenDummy.ComplexInput","name":"complexInput","type":"tuple"}],"name":"complexInputComplexOutput","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"foo","type":"uint256"},{"internalType":"bytes","name":"bar","type":"bytes"},{"internalType":"string","name":"car","type":"string"}],"internalType":"struct AbiGenDummy.ComplexInput","name":"input","type":"tuple"},{"internalType":"bytes","name":"lorem","type":"bytes"},{"internalType":"bytes","name":"ipsum","type":"bytes"},{"internalType":"string","name":"dolor","type":"string"}],"internalType":"struct AbiGenDummy.ComplexOutput","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ecrecoverFn","outputs":[{"internalType":"address","name":"signerAddress","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"emitSimpleEvent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct[][]","name":"index_0","type":"tuple[][]"}],"name":"methodAcceptingArrayOfArrayOfStructs","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct[]","name":"index_0","type":"tuple[]"}],"name":"methodAcceptingArrayOfStructs","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"methodReturningArrayOfStructs","outputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"methodReturningMultipleValues","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"methodUsingNestedStructWithInnerStructNotUsedElsewhere","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"aField","type":"uint256"}],"internalType":"struct AbiGenDummy.StructNotDirectlyUsedAnywhere","name":"innerStruct","type":"tuple"}],"internalType":"struct AbiGenDummy.NestedStructWithInnerStructNotUsedElsewhere","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"},{"internalType":"bytes","name":"index_1","type":"bytes"},{"internalType":"string","name":"index_2","type":"string"}],"name":"multiInputMultiOutput","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"innerStruct","type":"tuple"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct AbiGenDummy.NestedStruct","name":"n","type":"tuple"}],"name":"nestedStructInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"nestedStructOutput","outputs":[{"components":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"innerStruct","type":"tuple"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct AbiGenDummy.NestedStruct","name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"noInputNoOutput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"noInputSimpleOutput","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"nonPureMethodThatReturnsNothing","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"string","name":"a","type":"string"}],"name":"overloadedMethod","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"int256","name":"a","type":"int256"}],"name":"overloadedMethod","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"pureFunctionWithConstant","outputs":[{"internalType":"uint256","name":"someConstant","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"requireWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"revertWithConstant","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"}],"name":"simpleInputNoOutput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index_0","type":"uint256"}],"name":"simpleInputSimpleOutput","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simplePureFunction","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"simplePureFunctionWithInput","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRequire","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"simpleRevert","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"s","type":"tuple"}],"name":"structInput","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"structOutput","outputs":[{"components":[{"internalType":"bytes","name":"someBytes","type":"bytes"},{"internalType":"uint32","name":"anInteger","type":"uint32"},{"internalType":"bytes[]","name":"aDynamicArrayOfBytes","type":"bytes[]"},{"internalType":"string","name":"aString","type":"string"}],"internalType":"struct AbiGenDummy.Struct","name":"s","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"x","type":"address"},{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"},{"internalType":"address","name":"y","type":"address"},{"internalType":"uint256","name":"c","type":"uint256"}],"name":"withAddressInput","outputs":[{"internalType":"address","name":"z","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]' # noqa: E501 (line-too-long) ) diff --git a/packages/abi-gen/test-cli/output/python/lib_dummy/__init__.py b/packages/abi-gen/test-cli/output/python/lib_dummy/__init__.py index 6c1375710e..12e96c147f 100644 --- a/packages/abi-gen/test-cli/output/python/lib_dummy/__init__.py +++ b/packages/abi-gen/test-cli/output/python/lib_dummy/__init__.py @@ -90,7 +90,7 @@ class LibDummy: try: for middleware in MIDDLEWARE: web3.middleware_onion.inject( - middleware["function"], layer=middleware["layer"] + middleware["function"], layer=middleware["layer"], ) except ValueError as value_error: if value_error.args == ( diff --git a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts index d408c9538c..24ff6eb4e6 100644 --- a/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts +++ b/packages/abi-gen/test-cli/output/typescript/abi_gen_dummy.ts @@ -59,7 +59,7 @@ export class AbiGenDummyContract extends BaseContract { * @ignore */ public static deployedBytecode = - '0x608060405234801561001057600080fd5b50600436106101d95760003560e01c806376f15d5b11610104578063bb607362116100a2578063d88be12f11610071578063d88be12f1461039b578063ee8b86fb146103a3578063f408fb3114610279578063fa315f9d146103b6576101d9565b8063bb60736214610353578063bdab168814610369578063cd3c0b971461037e578063d6d7618c14610386576101d9565b80638ee52b4e116100de5780638ee52b4e146103225780639a3b618514610335578063a3c2f6b61461033d578063ae2dae1714610345576101d9565b806376f15d5b146102f25780637833bec0146102fa5780637a791e6e1461031a576101d9565b80634303a5421161017c57806359c28add1161014b57806359c28add146102b45780635ba3c7c0146102c957806363d69c88146102d1578063647341eb146102e4576101d9565b80634303a542146102875780634582eab21461028f57806345fdbdb714610297578063586f84b21461029f576101d9565b80632e1a7d4d116101b85780632e1a7d4d146102245780633687617d1461023757806336b32396146102595780633e9ef66a14610279576101d9565b806209e437146101de5780630527c28f146101e85780631310e444146101fb575b600080fd5b6101e66103c4565b005b6101e66101f6366004610c7f565b610401565b61020e610209366004610d87565b610404565b60405161021b91906113e8565b60405180910390f35b6101e6610232366004610d87565b61040b565b61024a610245366004610efc565b61045c565b60405161021b93929190611151565b61026c610267366004610d0b565b6104fc565b60405161021b9190611094565b6101e66101f6366004610d4c565b61020e6105de565b6101e66105e5565b6101e661064a565b6102a761067c565b60405161021b9190611373565b6102bc610684565b60405161021b919061137e565b6101e661068c565b61026c6102df366004610c2e565b6106f1565b6101e66101f6366004610ec9565b61020e6106fa565b61030d610308366004610d9f565b610708565b60405161021b9190611287565b6101e66107c5565b61020e610330366004610d87565b6107ca565b6101e66107d0565b61020e6107db565b6101e66101f6366004610e39565b61035b6107e0565b60405161021b9291906113f1565b610371610819565b60405161021b91906110b5565b6101e661081e565b61038e610855565b60405161021b91906113d5565b61020e6109ae565b6101e66103b1366004610d87565b6101f6565b6101e66101f6366004610d87565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611250565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b658260405161045191906113e8565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161054d929190611072565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105889493929190611133565b6020604051602081039080840390855afa1580156105aa573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103f690611219565b6105e26109b4565b6105e26109cc565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a00000000000000000000000000000000000000000000000000000000081526103f69190600401611193565b50929392505050565b600080546001019081905590565b6107106109ec565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b6103ff565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161084b906111ad565b60405180910390a1565b61085d610a1a565b6040805160028082526060828101909352816020015b60608152602001906001900390816108735790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108cd57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061091b57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109c7610a48565b905290565b60405180604001604052806109df610a1a565b8152602001606081525090565b60405180608001604052806109ff610a5b565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610a8c578081fd5b8135610a9f610a9a82611431565b61140a565b8181529150602080830190840160005b83811015610adc57610ac78760208435890101610ae6565b83526020928301929190910190600101610aaf565b5050505092915050565b600082601f830112610af6578081fd5b813567ffffffffffffffff811115610b0c578182fd5b610b3d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161140a565b9150808252836020828501011115610b5457600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610b7e578081fd5b610b88608061140a565b9050813567ffffffffffffffff80821115610ba257600080fd5b610bae85838601610ae6565b8352610bbd8560208601610c14565b60208401526040840135915080821115610bd657600080fd5b610be285838601610a7c565b60408401526060840135915080821115610bfb57600080fd5b50610c0884828501610ae6565b60608301525092915050565b803563ffffffff81168114610c2857600080fd5b92915050565b600080600080600060a08688031215610c45578081fd5b8535610c5081611481565b945060208601359350604086013592506060860135610c6e81611481565b949793965091946080013592915050565b60006020808385031215610c91578182fd5b823567ffffffffffffffff811115610ca7578283fd5b80840185601f820112610cb8578384fd5b80359150610cc8610a9a83611431565b82815283810190828501865b85811015610cfd57610ceb8a888435880101610ae6565b84529286019290860190600101610cd4565b509098975050505050505050565b60008060008060808587031215610d20578384fd5b84359350602085013560ff81168114610d37578384fd5b93969395505050506040820135916060013590565b600060208284031215610d5d578081fd5b813567ffffffffffffffff811115610d73578182fd5b610d7f84828501610ae6565b949350505050565b600060208284031215610d98578081fd5b5035919050565b600060208284031215610db0578081fd5b813567ffffffffffffffff80821115610dc7578283fd5b81840160608187031215610dd9578384fd5b610de3606061140a565b925080358352602081013582811115610dfa578485fd5b610e0687828401610ae6565b602085015250604081013582811115610e1d578485fd5b610e2987828401610ae6565b6040850152509195945050505050565b600060208284031215610e4a578081fd5b813567ffffffffffffffff80821115610e61578283fd5b81840160408187031215610e73578384fd5b610e7d604061140a565b9250803582811115610e8d578485fd5b610e9987828401610b6d565b845250602081013582811115610ead578485fd5b610eb987828401610ae6565b6020850152509195945050505050565b600060208284031215610eda578081fd5b813567ffffffffffffffff811115610ef0578182fd5b610d7f84828501610b6d565b600080600060608486031215610f10578081fd5b83359250602084013567ffffffffffffffff80821115610f2e578283fd5b610f3a87838801610ae6565b93506040860135915080821115610f4f578283fd5b50610f5c86828701610ae6565b9150509250925092565b60008151808452610f7e816020860160208601611451565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000815160808452610fc56080850182610f66565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b8285101561104b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868303018452611037828251610f66565b600195909501949387019391508601610ffd565b506060880151955088810360608a01526110658187610f66565b9998505050505050505050565b60008351611084818460208801611451565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611126577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452611114858351610fb0565b945092850192908501906001016110da565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526111646060830186610f66565b82810360208401526111768186610f66565b83810360408501526111888186610f66565b979650505050505050565b6000602082526111a66020830184610f66565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526112b7610100850182610f66565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e08601526112f28183610f66565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808584030160408601526113308383610f66565b604087015193508186820301606087015261134b8185610f66565b92505060608601519250808583030160808601525061136a8183610f66565b95945050505050565b905151815260200190565b60006020825282516040602084015261139a6060840182610fb0565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe084820301604085015261136a8183610f66565b6000602082526111a66020830184610fb0565b90815260200190565b600083825260406020830152610d7f6040830184610f66565b60405181810167ffffffffffffffff8111828210171561142957600080fd5b604052919050565b600067ffffffffffffffff821115611447578081fd5b5060209081020190565b60005b8381101561146c578181015183820152602001611454565b8381111561147b576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461040157600080fdfea365627a7a723158204f5b227587475ada330d11bfb46020f41172555bd06234eaaad1a7d10a4c2a396c6578706572696d656e74616cf564736f6c634300050c0040'; + '0x608060405234801561001057600080fd5b50600436106101ef5760003560e01c806377ec31ae1161010f578063bdab1688116100a2578063e796ee9611610071578063e796ee96146103c7578063ee8b86fb146103d5578063f408fb311461028f578063fa315f9d146103e8576101ef565b8063bdab16881461038d578063cd3c0b97146103a2578063d6d7618c146103aa578063d88be12f146103bf576101ef565b80639a3b6185116100de5780639a3b618514610359578063a3c2f6b614610361578063ae2dae1714610369578063bb60736214610377576101ef565b806377ec31ae146103105780637833bec01461031e5780637a791e6e1461033e5780638ee52b4e14610346576101ef565b80634582eab2116101875780635ba3c7c0116101565780635ba3c7c0146102df57806363d69c88146102e7578063647341eb146102fa57806376f15d5b14610308576101ef565b80634582eab2146102a557806345fdbdb7146102ad578063586f84b2146102b557806359c28add146102ca576101ef565b80633687617d116101c35780633687617d1461024d57806336b323961461026f5780633e9ef66a1461028f5780634303a5421461029d576101ef565b806209e437146101f45780630527c28f146101fe5780631310e444146102115780632e1a7d4d1461023a575b600080fd5b6101fc6103f6565b005b6101fc61020c366004610d98565b610433565b61022461021f366004610ec5565b610436565b6040516102319190611526565b60405180910390f35b6101fc610248366004610ec5565b61043d565b61026061025b36600461103a565b61048e565b6040516102319392919061128f565b61028261027d366004610e51565b61052e565b60405161023191906111d2565b6101fc61020c366004610e92565b610224610610565b6101fc610617565b6101fc61067c565b6102bd6106ae565b60405161023191906114b1565b6102d26106b6565b60405161023191906114bc565b6101fc6106be565b6102826102f5366004610cbb565b610723565b6101fc61020c366004611007565b61022461072c565b6101fc61020c366004610e16565b61033161032c366004610edd565b61073a565b60405161023191906113c5565b6101fc6107f7565b610224610354366004610ec5565b6107fc565b6101fc610802565b61022461080d565b6101fc61020c366004610f77565b61037f610812565b60405161023192919061152f565b61039561084b565b60405161023191906111f3565b6101fc610850565b6103b2610887565b6040516102319190611513565b6102246109e0565b6101fc61020c366004610d0c565b6101fc6103e3366004610ec5565b61020c565b6101fc61020c366004610ec5565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104289061138e565b60405180910390fd5b565b50565b506107c790565b3373ffffffffffffffffffffffffffffffffffffffff167f7fcf532c15f0a6db0bd6d0e038bea71d30d808c7d98cb3bf7268a95bf5081b65826040516104839190611526565b60405180910390a250565b505060408051808201825260048082527f1234567800000000000000000000000000000000000000000000000000000000602080840191909152835180850185528281527f87654321000000000000000000000000000000000000000000000000000000008183015284518086019095529184527f616d657400000000000000000000000000000000000000000000000000000000908401529093909250565b600060606040518060400160405280601c81526020017f19457468657265756d205369676e6564204d6573736167653a0a33320000000081525090506000818760405160200161057f9291906111b0565b604051602081830303815290604052805190602001209050600181878787604051600081526020016040526040516105ba9493929190611271565b6020604051602081039080840390855afa1580156105dc573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015198975050505050505050565b6107c75b90565b604080518082018252601481527f5245564552545f574954485f434f4e5354414e54000000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042890611357565b6106146109e6565b6106146109fe565b604080518082018252601581527f524551554952455f574954485f434f4e5354414e540000000000000000000000602082015290517f08c379a000000000000000000000000000000000000000000000000000000000815261042891906004016112d1565b50929392505050565b600080546001019081905590565b610742610a1e565b50604080516080810182529182528051808201825260048082527f123456780000000000000000000000000000000000000000000000000000000060208381019190915280850192909252825180840184528181527f87654321000000000000000000000000000000000000000000000000000000008184015284840152825180840190935282527f616d65740000000000000000000000000000000000000000000000000000000090820152606082015290565b610431565b60010190565b600080546001019055565b600190565b60408051808201909152600581527f68656c6c6f0000000000000000000000000000000000000000000000000000006020820152600191565b606090565b7f61a6029a4c7ddee5824d171331eecbd015d26a271310a223718b837facb5b77160405161087d906112eb565b60405180910390a1565b61088f610a4c565b6040805160028082526060828101909352816020015b60608152602001906001900390816108a55790505090506040518060400160405280600581526020017f3078313233000000000000000000000000000000000000000000000000000000815250816000815181106108ff57fe5b60200260200101819052506040518060400160405280600581526020017f30783332310000000000000000000000000000000000000000000000000000008152508160018151811061094d57fe5b6020908102919091018101919091526040805160c0810182526005608082018181527f307831323300000000000000000000000000000000000000000000000000000060a0840152825281840152808201939093528051808201909152600381527f6162630000000000000000000000000000000000000000000000000000000000918101919091526060820152905090565b6104d290565b60405180602001604052806109f9610a7a565b905290565b6040518060400160405280610a11610a4c565b8152602001606081525090565b6040518060800160405280610a31610a8d565b81526020016060815260200160608152602001606081525090565b604051806080016040528060608152602001600063ffffffff16815260200160608152602001606081525090565b6040518060200160405280600081525090565b60405180606001604052806000815260200160608152602001606081525090565b600082601f830112610abe578081fd5b8135610ad1610acc8261156f565b611548565b8181529150602080830190840160005b83811015610b0e57610af98760208435890101610b73565b83526020928301929190910190600101610ae1565b5050505092915050565b600082601f830112610b28578081fd5b8135610b36610acc8261156f565b8181529150602080830190840160005b83811015610b0e57610b5e8760208435890101610bfa565b83526020928301929190910190600101610b46565b600082601f830112610b83578081fd5b813567ffffffffffffffff811115610b99578182fd5b610bca60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611548565b9150808252836020828501011115610be157600080fd5b8060208401602084013760009082016020015292915050565b600060808284031215610c0b578081fd5b610c156080611548565b9050813567ffffffffffffffff80821115610c2f57600080fd5b610c3b85838601610b73565b8352610c4a8560208601610ca1565b60208401526040840135915080821115610c6357600080fd5b610c6f85838601610aae565b60408401526060840135915080821115610c8857600080fd5b50610c9584828501610b73565b60608301525092915050565b803563ffffffff81168114610cb557600080fd5b92915050565b600080600080600060a08688031215610cd2578081fd5b8535610cdd816115bf565b945060208601359350604086013592506060860135610cfb816115bf565b949793965091946080013592915050565b60006020808385031215610d1e578182fd5b823567ffffffffffffffff811115610d34578283fd5b80840185601f820112610d45578384fd5b80359150610d55610acc8361156f565b82815283810190828501865b85811015610d8a57610d788a888435880101610b18565b84529286019290860190600101610d61565b509098975050505050505050565b60006020808385031215610daa578182fd5b823567ffffffffffffffff811115610dc0578283fd5b80840185601f820112610dd1578384fd5b80359150610de1610acc8361156f565b82815283810190828501865b85811015610d8a57610e048a888435880101610b73565b84529286019290860190600101610ded565b600060208284031215610e27578081fd5b813567ffffffffffffffff811115610e3d578182fd5b610e4984828501610b18565b949350505050565b60008060008060808587031215610e66578182fd5b84359350602085013560ff81168114610e7d578283fd5b93969395505050506040820135916060013590565b600060208284031215610ea3578081fd5b813567ffffffffffffffff811115610eb9578182fd5b610e4984828501610b73565b600060208284031215610ed6578081fd5b5035919050565b600060208284031215610eee578081fd5b813567ffffffffffffffff80821115610f05578283fd5b81840160608187031215610f17578384fd5b610f216060611548565b925080358352602081013582811115610f38578485fd5b610f4487828401610b73565b602085015250604081013582811115610f5b578485fd5b610f6787828401610b73565b6040850152509195945050505050565b600060208284031215610f88578081fd5b813567ffffffffffffffff80821115610f9f578283fd5b81840160408187031215610fb1578384fd5b610fbb6040611548565b9250803582811115610fcb578485fd5b610fd787828401610bfa565b845250602081013582811115610feb578485fd5b610ff787828401610b73565b6020850152509195945050505050565b600060208284031215611018578081fd5b813567ffffffffffffffff81111561102e578182fd5b610e4984828501610bfa565b60008060006060848603121561104e578081fd5b83359250602084013567ffffffffffffffff8082111561106c578283fd5b61107887838801610b73565b9350604086013591508082111561108d578283fd5b5061109a86828701610b73565b9150509250925092565b600081518084526110bc81602086016020860161158f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081516080845261110360808501826110a4565b6020915063ffffffff828501511682860152604084015185820360408701528181518084528484019150848582028501018584018794505b82851015611189577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08683030184526111758282516110a4565b60019590950194938701939150860161113b565b506060880151955088810360608a01526111a381876110a4565b9998505050505050505050565b600083516111c281846020880161158f565b9190910191825250602001919050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611264577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526112528583516110ee565b94509285019290850190600101611218565b5092979650505050505050565b93845260ff9290921660208401526040830152606082015260800190565b6000606082526112a260608301866110a4565b82810360208401526112b481866110a4565b83810360408501526112c681866110a4565b979650505050505050565b6000602082526112e460208301846110a4565b9392505050565b60408082526004908201527f123456780000000000000000000000000000000000000000000000000000000060608201526080602082018190526005908201527f6c6f72656d00000000000000000000000000000000000000000000000000000060a082015260c00190565b6020808252600d908201527f53494d504c455f52455645525400000000000000000000000000000000000000604082015260600190565b6020808252600e908201527f53494d504c455f52455155495245000000000000000000000000000000000000604082015260600190565b600060208252825160806020840152805160a08401526020810151606060c08501526113f56101008501826110a4565b604083015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff608582030160e086015261143081836110a4565b9250505060208401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085840301604086015261146e83836110a4565b604087015193508186820301606087015261148981856110a4565b9250506060860151925080858303016080860152506114a881836110a4565b95945050505050565b905151815260200190565b6000602082528251604060208401526114d860608401826110ee565b602085015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526114a881836110a4565b6000602082526112e460208301846110ee565b90815260200190565b600083825260406020830152610e4960408301846110a4565b60405181810167ffffffffffffffff8111828210171561156757600080fd5b604052919050565b600067ffffffffffffffff821115611585578081fd5b5060209081020190565b60005b838110156115aa578181015183820152602001611592565b838111156115b9576000848401525b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116811461043357600080fdfea365627a7a72315820d4953afa8fe277a67a582a705ec911d7c404b5a84176ab0e36aa14da0e5986326c6578706572696d656e74616cf564736f6c63430005100040'; public static contractName = 'AbiGenDummy'; private readonly _methodABIIndex: { [name: string]: number } = {}; private readonly _subscriptionManager: SubscriptionManager; @@ -303,6 +303,70 @@ export class AbiGenDummyContract extends BaseContract { stateMutability: 'nonpayable', type: 'function', }, + { + constant: true, + inputs: [ + { + name: 'index_0', + type: 'tuple[][]', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + ], + name: 'methodAcceptingArrayOfArrayOfStructs', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, + { + constant: true, + inputs: [ + { + name: 'index_0', + type: 'tuple[]', + components: [ + { + name: 'someBytes', + type: 'bytes', + }, + { + name: 'anInteger', + type: 'uint32', + }, + { + name: 'aDynamicArrayOfBytes', + type: 'bytes[]', + }, + { + name: 'aString', + type: 'string', + }, + ], + }, + ], + name: 'methodAcceptingArrayOfStructs', + outputs: [], + payable: false, + stateMutability: 'pure', + type: 'function', + }, { constant: true, inputs: [], @@ -993,6 +1057,54 @@ export class AbiGenDummyContract extends BaseContract { }, }; } + public methodAcceptingArrayOfArrayOfStructs( + index_0: Array<{ + someBytes: string; + anInteger: number | BigNumber; + aDynamicArrayOfBytes: string[]; + aString: string; + }>[], + ): ContractFunctionObj { + const self = (this as any) as AbiGenDummyContract; + assert.isArray('index_0', index_0); + const functionSignature = 'methodAcceptingArrayOfArrayOfStructs((bytes,uint32,bytes[],string)[][])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [index_0]); + }, + }; + } + public methodAcceptingArrayOfStructs( + index_0: Array<{ + someBytes: string; + anInteger: number | BigNumber; + aDynamicArrayOfBytes: string[]; + aString: string; + }>, + ): ContractFunctionObj { + const self = (this as any) as AbiGenDummyContract; + assert.isArray('index_0', index_0); + const functionSignature = 'methodAcceptingArrayOfStructs((bytes,uint32,bytes[],string)[])'; + + return { + async callAsync(callData: Partial = {}, defaultBlock?: BlockParam): Promise { + BaseContract._assertCallParams(callData, defaultBlock); + const rawCallResult = await self._evmExecAsync(this.getABIEncodedTransactionData()); + const abiEncoder = self._lookupAbiEncoder(functionSignature); + return abiEncoder.strictDecodeReturnValue(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [index_0]); + }, + }; + } public methodReturningArrayOfStructs(): ContractFunctionObj< Array<{ someBytes: string; anInteger: number; aDynamicArrayOfBytes: string[]; aString: string }> > { diff --git a/packages/asset-swapper/CHANGELOG.json b/packages/asset-swapper/CHANGELOG.json index 0206c8baa7..e376a42ba7 100644 --- a/packages/asset-swapper/CHANGELOG.json +++ b/packages/asset-swapper/CHANGELOG.json @@ -9,6 +9,18 @@ { "note": "Remove `getSmartContractParamsOrThrow()` from `SwapQuoteConsumer`s.", "pr": 2432 + }, + { + "note": "Added `getBatchMarketBuySwapQuoteForAssetDataAsync` on `SwapQuoter`", + "pr": 2427 + }, + { + "note": "Add exponential sampling distribution and `sampleDistributionBase` option to `SwapQuoter`", + "pr": 2427 + }, + { + "note": "Compute more accurate best quote price", + "pr": 2427 } ] }, diff --git a/packages/asset-swapper/src/index.ts b/packages/asset-swapper/src/index.ts index 5327764bbc..cc0746c41a 100644 --- a/packages/asset-swapper/src/index.ts +++ b/packages/asset-swapper/src/index.ts @@ -54,6 +54,11 @@ export { SwapQuoteConsumerError, SignedOrderWithFillableAmounts, } from './types'; -export { ERC20BridgeSource } from './utils/market_operation_utils/types'; +export { + ERC20BridgeSource, + CollapsedFill, + NativeCollapsedFill, + OptimizedMarketOrder, +} from './utils/market_operation_utils/types'; export { affiliateFeeUtils } from './utils/affiliate_fee_utils'; export { ProtocolFeeUtils } from './utils/protocol_fee_utils'; diff --git a/packages/asset-swapper/src/swap_quoter.ts b/packages/asset-swapper/src/swap_quoter.ts index 2598501b28..f80408f60e 100644 --- a/packages/asset-swapper/src/swap_quoter.ts +++ b/packages/asset-swapper/src/swap_quoter.ts @@ -226,6 +226,58 @@ export class SwapQuoter { options, )) as MarketBuySwapQuote; } + + public async getBatchMarketBuySwapQuoteForAssetDataAsync( + makerAssetDatas: string[], + takerAssetData: string, + makerAssetBuyAmount: BigNumber[], + options: Partial = {}, + ): Promise> { + makerAssetBuyAmount.map((a, i) => assert.isBigNumber(`makerAssetBuyAmount[${i}]`, a)); + let gasPrice: BigNumber; + const { slippagePercentage, ...calculateSwapQuoteOpts } = _.merge( + {}, + constants.DEFAULT_SWAP_QUOTE_REQUEST_OPTS, + options, + ); + if (!!options.gasPrice) { + gasPrice = options.gasPrice; + assert.isBigNumber('gasPrice', gasPrice); + } else { + gasPrice = await this._protocolFeeUtils.getGasPriceEstimationOrThrowAsync(); + } + + const apiOrders = await this.orderbook.getBatchOrdersAsync(makerAssetDatas, [takerAssetData]); + const allOrders = apiOrders.map(orders => orders.map(o => o.order)); + const allPrunedOrders = allOrders.map((orders, i) => { + if (orders.length === 0) { + return [ + dummyOrderUtils.createDummyOrderForSampler( + makerAssetDatas[i], + takerAssetData, + this._contractAddresses.uniswapBridge, + ), + ]; + } else { + return sortingUtils.sortOrders( + orderPrunerUtils.pruneForUsableSignedOrders( + orders, + this.permittedOrderFeeTypes, + this.expiryBufferMs, + ), + ); + } + }); + + const swapQuotes = await this._swapQuoteCalculator.calculateBatchMarketBuySwapQuoteAsync( + allPrunedOrders, + makerAssetBuyAmount, + slippagePercentage, + gasPrice, + calculateSwapQuoteOpts, + ); + return swapQuotes; + } /** * Get a `SwapQuote` containing all information relevant to fulfilling a swap between a desired ERC20 token address and ERC20 owned by a provided address. * You can then pass the `SwapQuote` to a `SwapQuoteConsumer` to execute a buy, or process SwapQuote for on-chain consumption. diff --git a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts index ca0e6d981f..965079f144 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/constants.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/constants.ts @@ -24,12 +24,14 @@ export const SELL_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Da export const BUY_SOURCES = [ERC20BridgeSource.Uniswap, ERC20BridgeSource.Eth2Dai]; export const DEFAULT_GET_MARKET_ORDERS_OPTS: GetMarketOrdersOpts = { - runLimit: 4096, + // tslint:disable-next-line: custom-no-magic-numbers + runLimit: 2 ** 15, excludedSources: [], bridgeSlippage: 0.0005, - dustFractionThreshold: 0.01, - numSamples: 10, + dustFractionThreshold: 0.0025, + numSamples: 13, noConflicts: true, + sampleDistributionBase: 1.05, }; export const constants = { @@ -40,5 +42,5 @@ export const constants = { DEFAULT_GET_MARKET_ORDERS_OPTS, ERC20_PROXY_ID: '0xf47261b0', WALLET_SIGNATURE: '0x04', - SAMPLER_CONTRACT_GAS_LIMIT: 10e6, + SAMPLER_CONTRACT_GAS_LIMIT: 16e6, }; diff --git a/packages/asset-swapper/src/utils/market_operation_utils/create_order.ts b/packages/asset-swapper/src/utils/market_operation_utils/create_order.ts index d150da6376..bf64552106 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/create_order.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/create_order.ts @@ -3,11 +3,17 @@ import { assetDataUtils, generatePseudoRandomSalt } from '@0x/order-utils'; import { AbiEncoder, BigNumber } from '@0x/utils'; import { constants } from '../../constants'; -import { SignedOrderWithFillableAmounts } from '../../types'; import { sortingUtils } from '../../utils/sorting_utils'; import { constants as marketOperationUtilConstants } from './constants'; -import { AggregationError, ERC20BridgeSource, Fill, FillData, NativeFillData, OrderDomain } from './types'; +import { + AggregationError, + CollapsedFill, + ERC20BridgeSource, + NativeCollapsedFill, + OptimizedMarketOrder, + OrderDomain, +} from './types'; const { NULL_BYTES, NULL_ADDRESS, ZERO_AMOUNT } = constants; const { INFINITE_TIMESTAMP_SEC, WALLET_SIGNATURE } = marketOperationUtilConstants; @@ -24,23 +30,21 @@ export class CreateOrderUtils { orderDomain: OrderDomain, inputToken: string, outputToken: string, - path: Fill[], + path: CollapsedFill[], bridgeSlippage: number, - ): SignedOrderWithFillableAmounts[] { - const orders: SignedOrderWithFillableAmounts[] = []; + ): OptimizedMarketOrder[] { + const orders: OptimizedMarketOrder[] = []; for (const fill of path) { - const source = (fill.fillData as FillData).source; - if (source === ERC20BridgeSource.Native) { - orders.push((fill.fillData as NativeFillData).order); + if (fill.source === ERC20BridgeSource.Native) { + orders.push(createNativeOrder(fill)); } else { orders.push( createBridgeOrder( orderDomain, - this._getBridgeAddressFromSource(source), + fill, + this._getBridgeAddressFromSource(fill.source), outputToken, inputToken, - fill.output, - fill.input, bridgeSlippage, ), ); @@ -54,23 +58,21 @@ export class CreateOrderUtils { orderDomain: OrderDomain, inputToken: string, outputToken: string, - path: Fill[], + path: CollapsedFill[], bridgeSlippage: number, - ): SignedOrderWithFillableAmounts[] { - const orders: SignedOrderWithFillableAmounts[] = []; + ): OptimizedMarketOrder[] { + const orders: OptimizedMarketOrder[] = []; for (const fill of path) { - const source = (fill.fillData as FillData).source; - if (source === ERC20BridgeSource.Native) { - orders.push((fill.fillData as NativeFillData).order); + if (fill.source === ERC20BridgeSource.Native) { + orders.push(createNativeOrder(fill)); } else { orders.push( createBridgeOrder( orderDomain, - this._getBridgeAddressFromSource(source), + fill, + this._getBridgeAddressFromSource(fill.source), inputToken, outputToken, - fill.input, - fill.output, bridgeSlippage, true, ), @@ -97,14 +99,13 @@ export class CreateOrderUtils { function createBridgeOrder( orderDomain: OrderDomain, + fill: CollapsedFill, bridgeAddress: string, makerToken: string, takerToken: string, - makerAssetAmount: BigNumber, - takerAssetAmount: BigNumber, slippage: number, isBuy: boolean = false, -): SignedOrderWithFillableAmounts { +): OptimizedMarketOrder { return { makerAddress: bridgeAddress, makerAssetData: assetDataUtils.encodeERC20BridgeAssetData( @@ -113,7 +114,7 @@ function createBridgeOrder( createBridgeData(takerToken), ), takerAssetData: assetDataUtils.encodeERC20AssetData(takerToken), - ...createCommonOrderFields(orderDomain, makerAssetAmount, takerAssetAmount, slippage, isBuy), + ...createCommonOrderFields(orderDomain, fill, slippage, isBuy), }; } @@ -123,24 +124,24 @@ function createBridgeData(tokenAddress: string): string { } type CommonOrderFields = Pick< - SignedOrderWithFillableAmounts, - Exclude + OptimizedMarketOrder, + Exclude >; function createCommonOrderFields( orderDomain: OrderDomain, - makerAssetAmount: BigNumber, - takerAssetAmount: BigNumber, + fill: CollapsedFill, slippage: number, isBuy: boolean = false, ): CommonOrderFields { const makerAssetAmountAdjustedWithSlippage = isBuy - ? makerAssetAmount - : makerAssetAmount.times(1 - slippage).integerValue(BigNumber.ROUND_DOWN); + ? fill.totalMakerAssetAmount + : fill.totalMakerAssetAmount.times(1 - slippage).integerValue(BigNumber.ROUND_DOWN); const takerAssetAmountAdjustedWithSlippage = isBuy - ? takerAssetAmount.times(slippage + 1).integerValue(BigNumber.ROUND_UP) - : takerAssetAmount; + ? fill.totalTakerAssetAmount.times(slippage + 1).integerValue(BigNumber.ROUND_UP) + : fill.totalTakerAssetAmount; return { + fill, takerAddress: NULL_ADDRESS, senderAddress: NULL_ADDRESS, feeRecipientAddress: NULL_ADDRESS, @@ -159,3 +160,15 @@ function createCommonOrderFields( ...orderDomain, }; } + +function createNativeOrder(fill: CollapsedFill): OptimizedMarketOrder { + return { + fill: { + source: fill.source, + totalMakerAssetAmount: fill.totalMakerAssetAmount, + totalTakerAssetAmount: fill.totalTakerAssetAmount, + subFills: fill.subFills, + }, + ...(fill as NativeCollapsedFill).nativeOrder, + }; +} diff --git a/packages/asset-swapper/src/utils/market_operation_utils/index.ts b/packages/asset-swapper/src/utils/market_operation_utils/index.ts index 46584a57c9..aed438f35e 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/index.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/index.ts @@ -14,12 +14,16 @@ import { comparePathOutputs, FillsOptimizer, getPathOutput } from './fill_optimi import { DexOrderSampler } from './sampler'; import { AggregationError, + CollapsedFill, DexSample, ERC20BridgeSource, Fill, FillData, FillFlags, GetMarketOrdersOpts, + NativeCollapsedFill, + NativeFillData, + OptimizedMarketOrder, OrderDomain, } from './types'; @@ -53,7 +57,7 @@ export class MarketOperationUtils { nativeOrders: SignedOrder[], takerAmount: BigNumber, opts?: Partial, - ): Promise { + ): Promise { if (nativeOrders.length === 0) { throw new Error(AggregationError.EmptyOrders); } @@ -63,7 +67,7 @@ export class MarketOperationUtils { }; const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketSellAsync( nativeOrders, - DexOrderSampler.getSampleAmounts(takerAmount, _opts.numSamples), + DexOrderSampler.getSampleAmounts(takerAmount, _opts.numSamples, _opts.sampleDistributionBase), difference(SELL_SOURCES, _opts.excludedSources), ); const nativeOrdersWithFillableAmounts = createSignedOrdersWithFillableAmounts( @@ -77,8 +81,7 @@ export class MarketOperationUtils { takerAmount, _opts.dustFractionThreshold, ); - const clippedNativePath = clipPathToInput(prunedNativePath, takerAmount); - + const clippedNativePath = clipPathToInput(sortFillsByPrice(prunedNativePath), takerAmount); const dexPaths = createPathsFromDexQuotes(dexQuotes, _opts.noConflicts); const allPaths = [...dexPaths]; const allFills = flattenDexPaths(dexPaths); @@ -106,7 +109,7 @@ export class MarketOperationUtils { this._orderDomain, inputToken, outputToken, - simplifyPath(optimalPath), + collapsePath(optimalPath, false), _opts.bridgeSlippage, ); } @@ -123,7 +126,7 @@ export class MarketOperationUtils { nativeOrders: SignedOrder[], makerAmount: BigNumber, opts?: Partial, - ): Promise { + ): Promise { if (nativeOrders.length === 0) { throw new Error(AggregationError.EmptyOrders); } @@ -134,29 +137,86 @@ export class MarketOperationUtils { const [fillableAmounts, dexQuotes] = await this._dexSampler.getFillableAmountsAndSampleMarketBuyAsync( nativeOrders, - DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples), + DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples, _opts.sampleDistributionBase), difference(BUY_SOURCES, _opts.excludedSources), ); + const signedOrderWithFillableAmounts = this._createBuyOrdersPathFromSamplerResultIfExists( + nativeOrders, + makerAmount, + fillableAmounts, + dexQuotes, + _opts, + ); + if (!signedOrderWithFillableAmounts) { + throw new Error(AggregationError.NoOptimalPath); + } + return signedOrderWithFillableAmounts; + } + + /** + * gets the orders required for a batch of market buy operations by (potentially) merging native orders with + * generated bridge orders. + * @param batchNativeOrders Batch of Native orders. + * @param makerAmounts Array amount of maker asset to buy for each batch. + * @param opts Options object. + * @return orders. + */ + public async getBatchMarketBuyOrdersAsync( + batchNativeOrders: SignedOrder[][], + makerAmounts: BigNumber[], + opts?: Partial, + ): Promise> { + if (batchNativeOrders.length === 0) { + throw new Error(AggregationError.EmptyOrders); + } + const _opts = { + ...DEFAULT_GET_MARKET_ORDERS_OPTS, + ...opts, + }; + + const batchSampleResults = await this._dexSampler.getBatchFillableAmountsAndSampleMarketBuyAsync( + batchNativeOrders, + makerAmounts.map(makerAmount => DexOrderSampler.getSampleAmounts(makerAmount, _opts.numSamples)), + difference(BUY_SOURCES, _opts.excludedSources), + ); + return batchSampleResults.map(([fillableAmounts, dexQuotes], i) => + this._createBuyOrdersPathFromSamplerResultIfExists( + batchNativeOrders[i], + makerAmounts[i], + fillableAmounts, + dexQuotes, + _opts, + ), + ); + } + + private _createBuyOrdersPathFromSamplerResultIfExists( + nativeOrders: SignedOrder[], + makerAmount: BigNumber, + nativeOrderFillableAmounts: BigNumber[], + dexQuotes: DexSample[][], + opts: GetMarketOrdersOpts, + ): OptimizedMarketOrder[] | undefined { const nativeOrdersWithFillableAmounts = createSignedOrdersWithFillableAmounts( nativeOrders, - fillableAmounts, + nativeOrderFillableAmounts, MarketOperation.Buy, ); const prunedNativePath = pruneDustFillsFromNativePath( createBuyPathFromNativeOrders(nativeOrdersWithFillableAmounts), makerAmount, - _opts.dustFractionThreshold, + opts.dustFractionThreshold, ); - const clippedNativePath = clipPathToInput(prunedNativePath, makerAmount); - const dexPaths = createPathsFromDexQuotes(dexQuotes, _opts.noConflicts); + const clippedNativePath = clipPathToInput(sortFillsByPrice(prunedNativePath).reverse(), makerAmount); + const dexPaths = createPathsFromDexQuotes(dexQuotes, opts.noConflicts); const allPaths = [...dexPaths]; const allFills = flattenDexPaths(dexPaths); // If native orders are allowed, splice them in. - if (!_opts.excludedSources.includes(ERC20BridgeSource.Native)) { + if (!opts.excludedSources.includes(ERC20BridgeSource.Native)) { allPaths.splice(0, 0, clippedNativePath); allFills.splice(0, 0, ...clippedNativePath); } - const optimizer = new FillsOptimizer(_opts.runLimit, true); + const optimizer = new FillsOptimizer(opts.runLimit, true); const upperBoundPath = pickBestUpperBoundPath(allPaths, makerAmount, true); const optimalPath = optimizer.optimize( // Sorting the orders by price effectively causes the optimizer to walk @@ -167,15 +227,15 @@ export class MarketOperationUtils { upperBoundPath, ); if (!optimalPath) { - throw new Error(AggregationError.NoOptimalPath); + return undefined; } const [inputToken, outputToken] = getOrderTokens(nativeOrders[0]); return this._createOrderUtils.createBuyOrdersFromPath( this._orderDomain, inputToken, outputToken, - simplifyPath(optimalPath), - _opts.bridgeSlippage, + collapsePath(optimalPath, true), + opts.bridgeSlippage, ); } } @@ -186,26 +246,24 @@ function createSignedOrdersWithFillableAmounts( operation: MarketOperation, ): SignedOrderWithFillableAmounts[] { return signedOrders - .map( - (order: SignedOrder, i: number): SignedOrderWithFillableAmounts => { - const fillableAmount = fillableAmounts[i]; - const fillableMakerAssetAmount = - operation === MarketOperation.Buy - ? fillableAmount - : orderCalculationUtils.getMakerFillAmount(order, fillableAmount); - const fillableTakerAssetAmount = - operation === MarketOperation.Sell - ? fillableAmount - : orderCalculationUtils.getTakerFillAmount(order, fillableAmount); - const fillableTakerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, fillableTakerAssetAmount); - return { - fillableMakerAssetAmount, - fillableTakerAssetAmount, - fillableTakerFeeAmount, - ...order, - }; - }, - ) + .map((order: SignedOrder, i: number) => { + const fillableAmount = fillableAmounts[i]; + const fillableMakerAssetAmount = + operation === MarketOperation.Buy + ? fillableAmount + : orderCalculationUtils.getMakerFillAmount(order, fillableAmount); + const fillableTakerAssetAmount = + operation === MarketOperation.Sell + ? fillableAmount + : orderCalculationUtils.getTakerFillAmount(order, fillableAmount); + const fillableTakerFeeAmount = orderCalculationUtils.getTakerFeeAmount(order, fillableTakerAssetAmount); + return { + fillableMakerAssetAmount, + fillableTakerAssetAmount, + fillableTakerFeeAmount, + ...order, + }; + }) .filter(order => { return !order.fillableMakerAssetAmount.isZero() && !order.fillableTakerAssetAmount.isZero(); }); @@ -356,23 +414,31 @@ function getPathInput(path: Fill[]): BigNumber { } // Merges contiguous fills from the same DEX. -function simplifyPath(path: Fill[]): Fill[] { - const simplified: Fill[] = []; +function collapsePath(path: Fill[], isBuy: boolean): CollapsedFill[] { + const collapsed: Array = []; for (const fill of path) { + const makerAssetAmount = isBuy ? fill.input : fill.output; + const takerAssetAmount = isBuy ? fill.output : fill.input; const source = (fill.fillData as FillData).source; - if (simplified.length !== 0 && source !== ERC20BridgeSource.Native) { - const prevFill = simplified[simplified.length - 1]; - const prevSource = (prevFill.fillData as FillData).source; + if (collapsed.length !== 0 && source !== ERC20BridgeSource.Native) { + const prevFill = collapsed[collapsed.length - 1]; // If the last fill is from the same source, merge them. - if (prevSource === source) { - prevFill.input = prevFill.input.plus(fill.input); - prevFill.output = prevFill.output.plus(fill.output); + if (prevFill.source === source) { + prevFill.totalMakerAssetAmount = prevFill.totalMakerAssetAmount.plus(makerAssetAmount); + prevFill.totalTakerAssetAmount = prevFill.totalTakerAssetAmount.plus(takerAssetAmount); + prevFill.subFills.push({ makerAssetAmount, takerAssetAmount }); continue; } } - simplified.push(fill); + collapsed.push({ + source: fill.fillData.source, + totalMakerAssetAmount: makerAssetAmount, + totalTakerAssetAmount: takerAssetAmount, + subFills: [{ makerAssetAmount, takerAssetAmount }], + nativeOrder: (fill.fillData as NativeFillData).order, + }); } - return simplified; + return collapsed; } // Sort fills by descending price. diff --git a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts index 5ec107d0b2..078b5cd9cf 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/sampler.ts @@ -13,16 +13,14 @@ export class DexOrderSampler { /** * Generate sample amounts up to `maxFillAmount`. */ - public static getSampleAmounts(maxFillAmount: BigNumber, numSamples: number): BigNumber[] { - const amounts = []; - for (let i = 0; i < numSamples; i++) { - amounts.push( - maxFillAmount - .times(i + 1) - .div(numSamples) - .integerValue(BigNumber.ROUND_UP), - ); - } + public static getSampleAmounts(maxFillAmount: BigNumber, numSamples: number, expBase: number = 1): BigNumber[] { + const distribution = [...Array(numSamples)].map((v, i) => new BigNumber(expBase).pow(i)); + const stepSizes = distribution.map(d => d.div(BigNumber.sum(...distribution))); + const amounts = stepSizes.map((s, i) => { + return maxFillAmount + .times(BigNumber.sum(...[0, ...stepSizes.slice(0, i + 1)])) + .integerValue(BigNumber.ROUND_UP); + }); return amounts; } @@ -50,6 +48,36 @@ export class DexOrderSampler { return [fillableAmount, quotes]; } + public async getBatchFillableAmountsAndSampleMarketBuyAsync( + nativeOrders: SignedOrder[][], + sampleAmounts: BigNumber[][], + sources: ERC20BridgeSource[], + ): Promise> { + const signatures = nativeOrders.map(o => o.map(i => i.signature)); + const fillableAmountsAndSamples = await this._samplerContract + .queryBatchOrdersAndSampleBuys( + nativeOrders, + signatures, + sources.map(s => SOURCE_TO_ADDRESS[s]), + sampleAmounts, + ) + .callAsync(); + const batchFillableAmountsAndQuotes: Array<[BigNumber[], DexSample[][]]> = []; + fillableAmountsAndSamples.forEach((sampleResult, i) => { + const { tokenAmountsBySource, orderFillableAssetAmounts } = sampleResult; + const quotes = tokenAmountsBySource.map((rawDexSamples, sourceIdx) => { + const source = sources[sourceIdx]; + return rawDexSamples.map((sample, sampleIdx) => ({ + source, + input: sampleAmounts[i][sampleIdx], + output: sample, + })); + }); + batchFillableAmountsAndQuotes.push([orderFillableAssetAmounts, quotes]); + }); + return batchFillableAmountsAndQuotes; + } + public async getFillableAmountsAndSampleMarketSellAsync( nativeOrders: SignedOrder[], sampleAmounts: BigNumber[], diff --git a/packages/asset-swapper/src/utils/market_operation_utils/types.ts b/packages/asset-swapper/src/utils/market_operation_utils/types.ts index 20741162d4..0629579c74 100644 --- a/packages/asset-swapper/src/utils/market_operation_utils/types.ts +++ b/packages/asset-swapper/src/utils/market_operation_utils/types.ts @@ -79,6 +79,48 @@ export interface Fill { fillData: FillData | NativeFillData; } +/** + * Represents continguous fills on a path that have been merged together. + */ +export interface CollapsedFill { + /** + * The source DEX. + */ + source: ERC20BridgeSource; + /** + * Total maker asset amount. + */ + totalMakerAssetAmount: BigNumber; + /** + * Total taker asset amount. + */ + totalTakerAssetAmount: BigNumber; + /** + * All the fill asset amounts that were collapsed into this node. + */ + subFills: Array<{ + makerAssetAmount: BigNumber; + takerAssetAmount: BigNumber; + }>; +} + +/** + * A `CollapsedFill` wrapping a native order. + */ +export interface NativeCollapsedFill extends CollapsedFill { + nativeOrder: SignedOrderWithFillableAmounts; +} + +/** + * Optimized orders to fill. + */ +export interface OptimizedMarketOrder extends SignedOrderWithFillableAmounts { + /** + * The optimized fills that generated this order. + */ + fill: CollapsedFill; +} + /** * Options for `getMarketSellOrdersAsync()` and `getMarketBuyOrdersAsync()`. */ @@ -114,4 +156,12 @@ export interface GetMarketOrdersOpts { * Default is 0.01 (100 basis points). */ dustFractionThreshold: number; + /** + * The exponential sampling distribution base. + * A value of 1 will result in evenly spaced samples. + * > 1 will result in more samples at lower sizes. + * < 1 will result in more samples at higher sizes. + * Default: 1.25. + */ + sampleDistributionBase: number; } diff --git a/packages/asset-swapper/src/utils/protocol_fee_utils.ts b/packages/asset-swapper/src/utils/protocol_fee_utils.ts index 7040202ba7..a505c7e2c2 100644 --- a/packages/asset-swapper/src/utils/protocol_fee_utils.ts +++ b/packages/asset-swapper/src/utils/protocol_fee_utils.ts @@ -9,9 +9,9 @@ export class ProtocolFeeUtils { public gasPriceEstimation: BigNumber; private readonly _gasPriceHeart: any; - constructor(gasPricePollingIntervalInMs: number) { + constructor(gasPricePollingIntervalInMs: number, initialGasPrice: BigNumber = constants.ZERO_AMOUNT) { this._gasPriceHeart = heartbeats.createHeart(gasPricePollingIntervalInMs); - this.gasPriceEstimation = constants.ZERO_AMOUNT; + this.gasPriceEstimation = initialGasPrice; this._initializeHeartBeat(); } diff --git a/packages/asset-swapper/src/utils/swap_quote_calculator.ts b/packages/asset-swapper/src/utils/swap_quote_calculator.ts index 6463fae9eb..4b44b287a0 100644 --- a/packages/asset-swapper/src/utils/swap_quote_calculator.ts +++ b/packages/asset-swapper/src/utils/swap_quote_calculator.ts @@ -16,6 +16,7 @@ import { import { fillableAmountsUtils } from './fillable_amounts_utils'; import { MarketOperationUtils } from './market_operation_utils'; +import { ERC20BridgeSource, OptimizedMarketOrder } from './market_operation_utils/types'; import { ProtocolFeeUtils } from './protocol_fee_utils'; import { utils } from './utils'; @@ -63,6 +64,58 @@ export class SwapQuoteCalculator { )) as MarketBuySwapQuote; } + public async calculateBatchMarketBuySwapQuoteAsync( + batchPrunedOrders: SignedOrder[][], + takerAssetFillAmounts: BigNumber[], + slippagePercentage: number, + gasPrice: BigNumber, + opts: CalculateSwapQuoteOpts, + ): Promise> { + return (await this._calculateBatchBuySwapQuoteAsync( + batchPrunedOrders, + takerAssetFillAmounts, + slippagePercentage, + gasPrice, + MarketOperation.Buy, + opts, + )) as Array; + } + + private async _calculateBatchBuySwapQuoteAsync( + batchPrunedOrders: SignedOrder[][], + assetFillAmounts: BigNumber[], + slippagePercentage: number, + gasPrice: BigNumber, + operation: MarketOperation, + opts: CalculateSwapQuoteOpts, + ): Promise> { + const assetFillAmountsWithSlippage = assetFillAmounts.map(a => + a.plus(a.multipliedBy(slippagePercentage).integerValue()), + ); + const batchSignedOrders = await this._marketOperationUtils.getBatchMarketBuyOrdersAsync( + batchPrunedOrders, + assetFillAmountsWithSlippage, + opts, + ); + const batchSwapQuotes = await Promise.all( + batchSignedOrders.map(async (orders, i) => { + if (orders) { + const { makerAssetData, takerAssetData } = batchPrunedOrders[i][0]; + return this._createSwapQuoteAsync( + makerAssetData, + takerAssetData, + orders, + operation, + assetFillAmounts[i], + gasPrice, + ); + } else { + return undefined; + } + }), + ); + return batchSwapQuotes; + } private async _calculateSwapQuoteAsync( prunedOrders: SignedOrder[], assetFillAmount: BigNumber, @@ -74,7 +127,7 @@ export class SwapQuoteCalculator { // since prunedOrders do not have fillState, we will add a buffer of fillable orders to consider that some native are orders are partially filled const slippageBufferAmount = assetFillAmount.multipliedBy(slippagePercentage).integerValue(); - let resultOrders: SignedOrderWithFillableAmounts[] = []; + let resultOrders: OptimizedMarketOrder[] = []; if (operation === MarketOperation.Buy) { resultOrders = await this._marketOperationUtils.getMarketBuyOrdersAsync( @@ -91,28 +144,43 @@ export class SwapQuoteCalculator { } // assetData information for the result - const takerAssetData = prunedOrders[0].takerAssetData; - const makerAssetData = prunedOrders[0].makerAssetData; - + const { makerAssetData, takerAssetData } = prunedOrders[0]; + return this._createSwapQuoteAsync( + makerAssetData, + takerAssetData, + resultOrders, + operation, + assetFillAmount, + gasPrice, + ); + } + private async _createSwapQuoteAsync( + makerAssetData: string, + takerAssetData: string, + resultOrders: OptimizedMarketOrder[], + operation: MarketOperation, + assetFillAmount: BigNumber, + gasPrice: BigNumber, + ): Promise { const bestCaseQuoteInfo = await this._calculateQuoteInfoAsync( - createBestCaseOrders(resultOrders, operation, opts.bridgeSlippage), + resultOrders, assetFillAmount, gasPrice, operation, ); - // in order to calculate the maxRate, reverse the ordersAndFillableAmounts - // such that they are sorted from worst rate to best rate const worstCaseQuoteInfo = await this._calculateQuoteInfoAsync( - _.reverse(resultOrders.slice()), + resultOrders, assetFillAmount, gasPrice, operation, + true, ); const quoteBase = { takerAssetData, makerAssetData, - orders: resultOrders, + // Remove fill metadata. + orders: resultOrders.map(o => _.omit(o, 'fill')) as SignedOrderWithFillableAmounts[], bestCaseQuoteInfo, worstCaseQuoteInfo, gasPrice, @@ -135,31 +203,39 @@ export class SwapQuoteCalculator { // tslint:disable-next-line: prefer-function-over-method private async _calculateQuoteInfoAsync( - prunedOrders: SignedOrderWithFillableAmounts[], + orders: OptimizedMarketOrder[], assetFillAmount: BigNumber, gasPrice: BigNumber, operation: MarketOperation, + worstCase: boolean = false, ): Promise { if (operation === MarketOperation.Buy) { - return this._calculateMarketBuyQuoteInfoAsync(prunedOrders, assetFillAmount, gasPrice); + return this._calculateMarketBuyQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase); } else { - return this._calculateMarketSellQuoteInfoAsync(prunedOrders, assetFillAmount, gasPrice); + return this._calculateMarketSellQuoteInfoAsync(orders, assetFillAmount, gasPrice, worstCase); } } private async _calculateMarketSellQuoteInfoAsync( - prunedOrders: SignedOrderWithFillableAmounts[], + orders: OptimizedMarketOrder[], takerAssetSellAmount: BigNumber, gasPrice: BigNumber, + worstCase: boolean = false, ): Promise { - const result = prunedOrders.reduce( - (acc, order) => { - const { - totalMakerAssetAmount, - totalTakerAssetAmount, - totalFeeTakerAssetAmount, - remainingTakerAssetFillAmount, - } = acc; + let totalMakerAssetAmount = constants.ZERO_AMOUNT; + let totalTakerAssetAmount = constants.ZERO_AMOUNT; + let totalFeeTakerAssetAmount = constants.ZERO_AMOUNT; + let remainingTakerAssetFillAmount = takerAssetSellAmount; + const filledOrders = [] as OptimizedMarketOrder[]; + const _orders = !worstCase ? orders : orders.slice().reverse(); + for (const order of _orders) { + let makerAssetAmount = constants.ZERO_AMOUNT; + let takerAssetAmount = constants.ZERO_AMOUNT; + let feeTakerAssetAmount = constants.ZERO_AMOUNT; + if (remainingTakerAssetFillAmount.lte(0)) { + break; + } + if (order.fill.source === ERC20BridgeSource.Native) { const adjustedFillableMakerAssetAmount = fillableAmountsUtils.getMakerAssetAmountSwappedAfterFees( order, ); @@ -170,99 +246,155 @@ export class SwapQuoteCalculator { remainingTakerAssetFillAmount, adjustedFillableTakerAssetAmount, ); - const { takerAssetAmount, feeTakerAssetAmount } = getTakerAssetAmountBreakDown( - order, - takerAssetAmountWithFees, - ); - const makerAssetAmount = takerAssetAmountWithFees + const takerAssetAmountBreakDown = getTakerAssetAmountBreakDown(order, takerAssetAmountWithFees); + takerAssetAmount = takerAssetAmountBreakDown.takerAssetAmount; + feeTakerAssetAmount = takerAssetAmountBreakDown.feeTakerAssetAmount; + makerAssetAmount = takerAssetAmountWithFees .div(adjustedFillableTakerAssetAmount) - .multipliedBy(adjustedFillableMakerAssetAmount) + .times(adjustedFillableMakerAssetAmount) .integerValue(BigNumber.ROUND_DOWN); - return { - totalMakerAssetAmount: totalMakerAssetAmount.plus(makerAssetAmount), - totalTakerAssetAmount: totalTakerAssetAmount.plus(takerAssetAmount), - totalFeeTakerAssetAmount: totalFeeTakerAssetAmount.plus(feeTakerAssetAmount), - remainingTakerAssetFillAmount: BigNumber.max( - constants.ZERO_AMOUNT, - remainingTakerAssetFillAmount.minus(takerAssetAmountWithFees), - ), - }; - }, - { - totalMakerAssetAmount: constants.ZERO_AMOUNT, - totalTakerAssetAmount: constants.ZERO_AMOUNT, - totalFeeTakerAssetAmount: constants.ZERO_AMOUNT, - remainingTakerAssetFillAmount: takerAssetSellAmount, - }, - ); + } else { + // This is a collapsed bridge order. + // Because collapsed bridge orders actually fill at different rates, + // we can iterate over the uncollapsed fills to get the actual + // asset amounts transfered. + // We can also assume there are no fees and the order is not + // partially filled. + + // Infer the bridge slippage from the difference between the fill + // size and the actual order asset amounts. + const makerAssetBridgeSlippage = !worstCase + ? constants.ONE_AMOUNT + : order.makerAssetAmount.div(order.fill.totalMakerAssetAmount); + const takerAssetBridgeSlippage = !worstCase + ? constants.ONE_AMOUNT + : order.takerAssetAmount.div(order.fill.totalTakerAssetAmount); + // Consecutively fill the subfills in this order. + const subFills = !worstCase ? order.fill.subFills : order.fill.subFills.slice().reverse(); + for (const subFill of subFills) { + if (remainingTakerAssetFillAmount.minus(takerAssetAmount).lte(0)) { + break; + } + const partialTakerAssetAmount = subFill.takerAssetAmount.times(takerAssetBridgeSlippage); + const partialMakerAssetAmount = subFill.makerAssetAmount.times(makerAssetBridgeSlippage); + const partialTakerAssetFillAmount = BigNumber.min( + partialTakerAssetAmount, + remainingTakerAssetFillAmount.minus(takerAssetAmount), + ); + const partialMakerAssetFillAmount = partialTakerAssetFillAmount + .div(partialTakerAssetAmount) + .times(partialMakerAssetAmount) + .integerValue(BigNumber.ROUND_DOWN); + takerAssetAmount = takerAssetAmount.plus(partialTakerAssetFillAmount); + makerAssetAmount = makerAssetAmount.plus(partialMakerAssetFillAmount); + } + } + totalMakerAssetAmount = totalMakerAssetAmount.plus(makerAssetAmount); + totalTakerAssetAmount = totalTakerAssetAmount.plus(takerAssetAmount); + totalFeeTakerAssetAmount = totalFeeTakerAssetAmount.plus(feeTakerAssetAmount); + remainingTakerAssetFillAmount = remainingTakerAssetFillAmount + .minus(takerAssetAmount) + .minus(feeTakerAssetAmount); + filledOrders.push(order); + } const protocolFeeInWeiAmount = await this._protocolFeeUtils.calculateWorstCaseProtocolFeeAsync( - prunedOrders, + filledOrders, gasPrice, ); return { - feeTakerAssetAmount: result.totalFeeTakerAssetAmount, - takerAssetAmount: result.totalTakerAssetAmount, - totalTakerAssetAmount: result.totalFeeTakerAssetAmount.plus(result.totalTakerAssetAmount), - makerAssetAmount: result.totalMakerAssetAmount, + feeTakerAssetAmount: totalFeeTakerAssetAmount, + takerAssetAmount: totalTakerAssetAmount, + totalTakerAssetAmount: totalFeeTakerAssetAmount.plus(totalTakerAssetAmount), + makerAssetAmount: totalMakerAssetAmount, protocolFeeInWeiAmount, }; } private async _calculateMarketBuyQuoteInfoAsync( - prunedOrders: SignedOrderWithFillableAmounts[], + orders: OptimizedMarketOrder[], makerAssetBuyAmount: BigNumber, gasPrice: BigNumber, + worstCase: boolean = false, ): Promise { - const result = prunedOrders.reduce( - (acc, order) => { - const { - totalMakerAssetAmount, - totalTakerAssetAmount, - totalFeeTakerAssetAmount, - remainingMakerAssetFillAmount, - } = acc; + let totalMakerAssetAmount = constants.ZERO_AMOUNT; + let totalTakerAssetAmount = constants.ZERO_AMOUNT; + let totalFeeTakerAssetAmount = constants.ZERO_AMOUNT; + let remainingMakerAssetFillAmount = makerAssetBuyAmount; + const filledOrders = [] as OptimizedMarketOrder[]; + const _orders = !worstCase ? orders : orders.slice().reverse(); + for (const order of _orders) { + let makerAssetAmount = constants.ZERO_AMOUNT; + let takerAssetAmount = constants.ZERO_AMOUNT; + let feeTakerAssetAmount = constants.ZERO_AMOUNT; + if (remainingMakerAssetFillAmount.lte(0)) { + break; + } + if (order.fill.source === ERC20BridgeSource.Native) { const adjustedFillableMakerAssetAmount = fillableAmountsUtils.getMakerAssetAmountSwappedAfterFees( order, ); const adjustedFillableTakerAssetAmount = fillableAmountsUtils.getTakerAssetAmountSwappedAfterFees( order, ); - const makerFillAmount = BigNumber.min(remainingMakerAssetFillAmount, adjustedFillableMakerAssetAmount); - const takerAssetAmountWithFees = makerFillAmount + makerAssetAmount = BigNumber.min(remainingMakerAssetFillAmount, adjustedFillableMakerAssetAmount); + const takerAssetAmountWithFees = makerAssetAmount .div(adjustedFillableMakerAssetAmount) .multipliedBy(adjustedFillableTakerAssetAmount) .integerValue(BigNumber.ROUND_UP); + const takerAssetAmountBreakDown = getTakerAssetAmountBreakDown(order, takerAssetAmountWithFees); + takerAssetAmount = takerAssetAmountBreakDown.takerAssetAmount; + feeTakerAssetAmount = takerAssetAmountBreakDown.feeTakerAssetAmount; + } else { + // This is a collapsed bridge order. + // Because collapsed bridge orders actually fill at different rates, + // we can iterate over the uncollapsed fills to get the actual + // asset amounts transfered. + // We can also assume there are no fees and the order is not + // partially filled. - const { takerAssetAmount, feeTakerAssetAmount } = getTakerAssetAmountBreakDown( - order, - takerAssetAmountWithFees, - ); - return { - totalMakerAssetAmount: totalMakerAssetAmount.plus(makerFillAmount), - totalTakerAssetAmount: totalTakerAssetAmount.plus(takerAssetAmount), - totalFeeTakerAssetAmount: totalFeeTakerAssetAmount.plus(feeTakerAssetAmount), - remainingMakerAssetFillAmount: BigNumber.max( - constants.ZERO_AMOUNT, - remainingMakerAssetFillAmount.minus(makerFillAmount), - ), - }; - }, - { - totalMakerAssetAmount: constants.ZERO_AMOUNT, - totalTakerAssetAmount: constants.ZERO_AMOUNT, - totalFeeTakerAssetAmount: constants.ZERO_AMOUNT, - remainingMakerAssetFillAmount: makerAssetBuyAmount, - }, - ); + // Infer the bridge slippage from the difference between the fill + // size and the actual order asset amounts. + const makerAssetBridgeSlippage = !worstCase + ? constants.ONE_AMOUNT + : order.makerAssetAmount.div(order.fill.totalMakerAssetAmount); + const takerAssetBridgeSlippage = !worstCase + ? constants.ONE_AMOUNT + : order.takerAssetAmount.div(order.fill.totalTakerAssetAmount); + // Consecutively fill the subfills in this order. + const subFills = !worstCase ? order.fill.subFills : order.fill.subFills.slice().reverse(); + for (const subFill of subFills) { + if (remainingMakerAssetFillAmount.minus(makerAssetAmount).lte(0)) { + break; + } + const partialTakerAssetAmount = subFill.takerAssetAmount.times(takerAssetBridgeSlippage); + const partialMakerAssetAmount = subFill.makerAssetAmount.times(makerAssetBridgeSlippage); + const partialMakerAssetFillAmount = BigNumber.min( + partialMakerAssetAmount, + remainingMakerAssetFillAmount.minus(makerAssetAmount), + ); + const partialTakerAssetFillAmount = partialMakerAssetFillAmount + .div(partialMakerAssetAmount) + .times(partialTakerAssetAmount) + .integerValue(BigNumber.ROUND_UP); + takerAssetAmount = takerAssetAmount.plus(partialTakerAssetFillAmount); + makerAssetAmount = makerAssetAmount.plus(partialMakerAssetFillAmount); + } + } + totalMakerAssetAmount = totalMakerAssetAmount.plus(makerAssetAmount); + totalTakerAssetAmount = totalTakerAssetAmount.plus(takerAssetAmount); + totalFeeTakerAssetAmount = totalFeeTakerAssetAmount.plus(feeTakerAssetAmount); + remainingMakerAssetFillAmount = remainingMakerAssetFillAmount.minus(makerAssetAmount); + filledOrders.push(order); + } const protocolFeeInWeiAmount = await this._protocolFeeUtils.calculateWorstCaseProtocolFeeAsync( - prunedOrders, + filledOrders, gasPrice, ); return { - feeTakerAssetAmount: result.totalFeeTakerAssetAmount, - takerAssetAmount: result.totalTakerAssetAmount, - totalTakerAssetAmount: result.totalFeeTakerAssetAmount.plus(result.totalTakerAssetAmount), - makerAssetAmount: result.totalMakerAssetAmount, + feeTakerAssetAmount: totalFeeTakerAssetAmount, + takerAssetAmount: totalTakerAssetAmount, + totalTakerAssetAmount: totalFeeTakerAssetAmount.plus(totalTakerAssetAmount), + makerAssetAmount: totalMakerAssetAmount, protocolFeeInWeiAmount, }; } @@ -303,35 +435,3 @@ function getTakerAssetAmountBreakDown( takerAssetAmount: takerAssetAmountWithFees, }; } - -function createBestCaseOrders( - orders: SignedOrderWithFillableAmounts[], - operation: MarketOperation, - bridgeSlippage: number, -): SignedOrderWithFillableAmounts[] { - // Scale the asset amounts to undo the bridge slippage applied to - // bridge orders. - const bestCaseOrders: SignedOrderWithFillableAmounts[] = []; - for (const order of orders) { - if (!order.makerAssetData.startsWith(constants.BRIDGE_ASSET_DATA_PREFIX)) { - bestCaseOrders.push(order); - continue; - } - bestCaseOrders.push({ - ...order, - ...(operation === MarketOperation.Sell - ? { - makerAssetAmount: order.makerAssetAmount - .dividedBy(1 - bridgeSlippage) - .integerValue(BigNumber.ROUND_DOWN), - } - : // Buy operation - { - takerAssetAmount: order.takerAssetAmount - .dividedBy(bridgeSlippage + 1) - .integerValue(BigNumber.ROUND_UP), - }), - }); - } - return bestCaseOrders; -} diff --git a/packages/asset-swapper/test/calculate_liquidity_test.ts b/packages/asset-swapper/test/calculate_liquidity_test.ts index 308e98813f..3f20737c48 100644 --- a/packages/asset-swapper/test/calculate_liquidity_test.ts +++ b/packages/asset-swapper/test/calculate_liquidity_test.ts @@ -23,7 +23,7 @@ describe('#calculateLiquidity', () => { const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity( prunedSignedOrders, ); - expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(10)); + expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(11)); expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(9)); }); it('should provide correct liquidity result with orders with takerFees in takerAsset', () => { @@ -31,7 +31,7 @@ describe('#calculateLiquidity', () => { const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity( prunedSignedOrders, ); - expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(10)); + expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(11)); expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(15)); }); it('should provide correct liquidity result with orders with takerFees in makerAsset', () => { @@ -51,7 +51,7 @@ describe('#calculateLiquidity', () => { const { makerAssetAvailableInBaseUnits, takerAssetAvailableInBaseUnits } = calculateLiquidity( prunedSignedOrders, ); - expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(25)); + expect(makerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(27)); expect(takerAssetAvailableInBaseUnits).to.bignumber.eq(baseUnitAmount(33)); }); }); diff --git a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts index 1143f5d477..3321aaac5f 100644 --- a/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts +++ b/packages/asset-swapper/test/exchange_swap_quote_consumer_test.ts @@ -123,7 +123,7 @@ describe('ExchangeSwapQuoteConsumer', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); - protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS); + protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1)); expectMakerAndTakerBalancesForTakerAssetAsync = expectMakerAndTakerBalancesAsyncFactory( erc20TakerTokenContract, makerAddress, diff --git a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts index 06d902cb50..0113fe86ee 100644 --- a/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts +++ b/packages/asset-swapper/test/forwarder_swap_quote_consumer_test.ts @@ -126,7 +126,7 @@ describe('ForwarderSwapQuoteConsumer', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); - protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS); + protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1)); expectMakerAndTakerBalancesAsync = expectMakerAndTakerBalancesAsyncFactory( erc20TokenContract, makerAddress, diff --git a/packages/asset-swapper/test/market_operation_utils_test.ts b/packages/asset-swapper/test/market_operation_utils_test.ts index f7b5575044..0145930f09 100644 --- a/packages/asset-swapper/test/market_operation_utils_test.ts +++ b/packages/asset-swapper/test/market_operation_utils_test.ts @@ -306,7 +306,7 @@ describe('MarketOperationUtils tests', () => { _.times(3, () => SOURCE_RATES[ERC20BridgeSource.Native][0]), ); const DEFAULT_SAMPLER = createSamplerFromSellRates(SOURCE_RATES); - const DEFAULT_OPTS = { numSamples: 3, runLimit: 0 }; + const DEFAULT_OPTS = { numSamples: 3, runLimit: 0, sampleDistributionBase: 1 }; const defaultMarketOperationUtils = new MarketOperationUtils( DEFAULT_SAMPLER, contractAddresses, @@ -552,7 +552,7 @@ describe('MarketOperationUtils tests', () => { _.times(3, () => SOURCE_RATES[ERC20BridgeSource.Native][0]), ); const DEFAULT_SAMPLER = createSamplerFromBuyRates(SOURCE_RATES); - const DEFAULT_OPTS = { numSamples: 3, runLimit: 0 }; + const DEFAULT_OPTS = { numSamples: 3, runLimit: 0, sampleDistributionBase: 1 }; const defaultMarketOperationUtils = new MarketOperationUtils( DEFAULT_SAMPLER, contractAddresses, diff --git a/packages/asset-swapper/test/swap_quote_calculator_test.ts b/packages/asset-swapper/test/swap_quote_calculator_test.ts index a8c760d9a0..f595683065 100644 --- a/packages/asset-swapper/test/swap_quote_calculator_test.ts +++ b/packages/asset-swapper/test/swap_quote_calculator_test.ts @@ -65,6 +65,9 @@ const createSamplerFromSignedOrdersWithFillableAmounts = ( return sampler; }; +// TODO(dorothy-zbornak): Replace these tests entirely with unit tests because +// omg they're a nightmare to maintain. + // tslint:disable:max-file-line-count // tslint:disable:custom-no-magic-numbers describe('swapQuoteCalculator', () => { @@ -272,7 +275,7 @@ describe('swapQuoteCalculator', () => { }); }); it('calculates a correct swapQuote with slippage (feeless orders)', async () => { - const assetSellAmount = baseUnitAmount(1); + const assetSellAmount = baseUnitAmount(4); const slippagePercentage = 0.2; const sampler = createSamplerFromSignedOrdersWithFillableAmounts( testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS, @@ -289,10 +292,10 @@ describe('swapQuoteCalculator', () => { GAS_PRICE, CALCULATE_SWAP_QUOTE_OPTS, ); - // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[0], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[2], testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[1], ]); expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount); @@ -301,15 +304,15 @@ describe('swapQuoteCalculator', () => { feeTakerAssetAmount: baseUnitAmount(0), takerAssetAmount: assetSellAmount, totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(6), + makerAssetAmount: baseUnitAmount(9), protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ feeTakerAssetAmount: baseUnitAmount(0), takerAssetAmount: assetSellAmount, totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(0.4), - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + makerAssetAmount: baseUnitAmount(1.6), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); }); it('calculates a correct swapQuote with no slippage (takerAsset denominated fee orders)', async () => { @@ -372,7 +375,7 @@ describe('swapQuoteCalculator', () => { // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[0], - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[1], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[2], ]); expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount); // test if rates are correct @@ -381,14 +384,14 @@ describe('swapQuoteCalculator', () => { takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2.25)), totalTakerAssetAmount: assetSellAmount, makerAssetAmount: baseUnitAmount(4.5), - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(0.5), - takerAssetAmount: assetSellAmount.minus(baseUnitAmount(0.5)), + feeTakerAssetAmount: baseUnitAmount(1.2), + takerAssetAmount: assetSellAmount.minus(baseUnitAmount(1.2)), totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(1), - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + makerAssetAmount: baseUnitAmount(1.8), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); }); it('calculates a correct swapQuote with no slippage (makerAsset denominated fee orders)', async () => { @@ -411,23 +414,24 @@ describe('swapQuoteCalculator', () => { ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[0], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[1], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[2], ]); expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount); // test if rates are correct expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2), - takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)), + feeTakerAssetAmount: baseUnitAmount(1.5).minus(1), + takerAssetAmount: assetSellAmount.minus(baseUnitAmount(1.5)).plus(1), totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(0.8), - protocolFeeInWeiAmount: baseUnitAmount(15, 4), + makerAssetAmount: baseUnitAmount(4), + protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2), - takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)), + feeTakerAssetAmount: baseUnitAmount(1.5).minus(1), + takerAssetAmount: assetSellAmount.minus(baseUnitAmount(1.5)).plus(1), totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(0.8), - protocolFeeInWeiAmount: baseUnitAmount(15, 4), + makerAssetAmount: baseUnitAmount(4), + protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); }); it('calculates a correct swapQuote with slippage (makerAsset denominated fee orders)', async () => { @@ -451,24 +455,24 @@ describe('swapQuoteCalculator', () => { // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[1], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[2], testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[0], ]); expect(swapQuote.takerAssetFillAmount).to.bignumber.equal(assetSellAmount); // test if rates are correct - // 50 takerAsset units to fill the first order + 100 takerAsset units for fees + expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({ + feeTakerAssetAmount: baseUnitAmount(1.5).minus(1), + takerAssetAmount: assetSellAmount.minus(baseUnitAmount(1.5)).plus(1), + totalTakerAssetAmount: assetSellAmount, + makerAssetAmount: baseUnitAmount(4), + protocolFeeInWeiAmount: baseUnitAmount(30, 4), + }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ feeTakerAssetAmount: baseUnitAmount(2), takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)), totalTakerAssetAmount: assetSellAmount, makerAssetAmount: baseUnitAmount(0.8), - protocolFeeInWeiAmount: baseUnitAmount(30, 4), - }); - expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2), - takerAssetAmount: assetSellAmount.minus(baseUnitAmount(2)), - totalTakerAssetAmount: assetSellAmount, - makerAssetAmount: baseUnitAmount(3.6), - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); }); }); @@ -678,7 +682,7 @@ describe('swapQuoteCalculator', () => { // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[0], - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[1], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS[2], ]); expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount); @@ -692,12 +696,16 @@ describe('swapQuoteCalculator', () => { takerAssetAmount, totalTakerAssetAmount: takerAssetAmount, makerAssetAmount: assetBuyAmount, - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ feeTakerAssetAmount: baseUnitAmount(0), - takerAssetAmount: baseUnitAmount(5.5), - totalTakerAssetAmount: baseUnitAmount(5.5), + takerAssetAmount: baseUnitAmount(20) + .div(6) + .integerValue(BigNumber.ROUND_UP), + totalTakerAssetAmount: baseUnitAmount(20) + .div(6) + .integerValue(BigNumber.ROUND_UP), makerAssetAmount: assetBuyAmount, protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); @@ -766,7 +774,7 @@ describe('swapQuoteCalculator', () => { // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[0], - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[1], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_TAKER_ASSET[2], ]); expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount); // test if rates are correct @@ -775,12 +783,16 @@ describe('swapQuoteCalculator', () => { takerAssetAmount: fiveSixthEthInWei, totalTakerAssetAmount: baseUnitAmount(2.5).plus(fiveSixthEthInWei), makerAssetAmount: assetBuyAmount, - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2.5), - takerAssetAmount: baseUnitAmount(5.5), - totalTakerAssetAmount: baseUnitAmount(8), + feeTakerAssetAmount: baseUnitAmount(3), + takerAssetAmount: baseUnitAmount(10) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 3.3333... + totalTakerAssetAmount: baseUnitAmount(19) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 6.3333... makerAssetAmount: assetBuyAmount, protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); @@ -805,21 +817,33 @@ describe('swapQuoteCalculator', () => { ); // test if orders are correct expect(swapQuote.orders).to.deep.equal([ - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[0], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[1], ]); expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount); // test if rates are correct expect(swapQuote.bestCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2.5), - takerAssetAmount: baseUnitAmount(2.5), - totalTakerAssetAmount: baseUnitAmount(5), + feeTakerAssetAmount: baseUnitAmount(0.5) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.16666... + takerAssetAmount: baseUnitAmount(0.5) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.1666... + totalTakerAssetAmount: baseUnitAmount(1) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.3333... makerAssetAmount: assetBuyAmount, protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2.5), - takerAssetAmount: baseUnitAmount(2.5), - totalTakerAssetAmount: baseUnitAmount(5), + feeTakerAssetAmount: baseUnitAmount(0.5) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.16666... + takerAssetAmount: baseUnitAmount(0.5) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.1666... + totalTakerAssetAmount: baseUnitAmount(1) + .div(3) + .integerValue(BigNumber.ROUND_UP), // 0.3333... makerAssetAmount: assetBuyAmount, protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); @@ -845,14 +869,14 @@ describe('swapQuoteCalculator', () => { // test if orders are correct expect(swapQuote.orders).to.deep.equal([ testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[1], - testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[0], + testOrders.SIGNED_ORDERS_WITH_FILLABLE_AMOUNTS_FEE_IN_MAKER_ASSET[2], ]); expect(swapQuote.makerAssetFillAmount).to.bignumber.equal(assetBuyAmount); // test if rates are correct expect(swapQuote.worstCaseQuoteInfo).to.deep.equal({ - feeTakerAssetAmount: baseUnitAmount(2.75), - takerAssetAmount: baseUnitAmount(2.75), - totalTakerAssetAmount: baseUnitAmount(5.5), + feeTakerAssetAmount: baseUnitAmount(1.25).minus(1), + takerAssetAmount: baseUnitAmount(2.25).plus(1), + totalTakerAssetAmount: baseUnitAmount(3.5), makerAssetAmount: assetBuyAmount, protocolFeeInWeiAmount: baseUnitAmount(30, 4), }); @@ -879,7 +903,7 @@ describe('swapQuoteCalculator', () => { .multipliedBy(0.1) .integerValue(BigNumber.ROUND_CEIL), makerAssetAmount: assetBuyAmount, - protocolFeeInWeiAmount: baseUnitAmount(30, 4), + protocolFeeInWeiAmount: baseUnitAmount(15, 4), }); }); }); diff --git a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts index 392f378dc1..5c80acaee0 100644 --- a/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts +++ b/packages/asset-swapper/test/swap_quote_consumer_utils_test.ts @@ -119,7 +119,7 @@ describe('swapQuoteConsumerUtils', () => { }; const privateKey = devConstants.TESTRPC_PRIVATE_KEYS[userAddresses.indexOf(makerAddress)]; orderFactory = new OrderFactory(privateKey, defaultOrderParams); - protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS); + protocolFeeUtils = new ProtocolFeeUtils(constants.PROTOCOL_FEE_UTILS_POLLING_INTERVAL_IN_MS, new BigNumber(1)); forwarderOrderFactory = new OrderFactory(privateKey, defaultForwarderOrderParams); swapQuoteConsumer = new SwapQuoteConsumer(provider, { diff --git a/packages/asset-swapper/test/utils/test_orders.ts b/packages/asset-swapper/test/utils/test_orders.ts index 3817b57783..5a2581c231 100644 --- a/packages/asset-swapper/test/utils/test_orders.ts +++ b/packages/asset-swapper/test/utils/test_orders.ts @@ -51,7 +51,7 @@ const PARTIAL_ORDERS_WITH_FILLABLE_AMOUNTS_FEELESS: Array + >, + orderSignatures: string[][], + sources: string[], + makerTokenAmounts: BigNumber[][], + ): ContractFunctionObj> { + const self = (this as any) as IERC20BridgeSamplerContract; + assert.isArray('orders', orders); + assert.isArray('orderSignatures', orderSignatures); + assert.isArray('sources', sources); + assert.isArray('makerTokenAmounts', makerTokenAmounts); + const functionSignature = + 'queryBatchOrdersAndSampleBuys((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],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); + return abiEncoder.strictDecodeReturnValue< + Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> + >(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [ + orders, + orderSignatures, + sources, + makerTokenAmounts, + ]); + }, + }; + } + public queryBatchOrdersAndSampleSells( + orders: Array< + Array<{ + makerAddress: string; + takerAddress: string; + feeRecipientAddress: string; + senderAddress: string; + makerAssetAmount: BigNumber; + takerAssetAmount: BigNumber; + makerFee: BigNumber; + takerFee: BigNumber; + expirationTimeSeconds: BigNumber; + salt: BigNumber; + makerAssetData: string; + takerAssetData: string; + makerFeeAssetData: string; + takerFeeAssetData: string; + }> + >, + orderSignatures: string[][], + sources: string[], + takerTokenAmounts: BigNumber[][], + ): ContractFunctionObj> { + const self = (this as any) as IERC20BridgeSamplerContract; + assert.isArray('orders', orders); + assert.isArray('orderSignatures', orderSignatures); + assert.isArray('sources', sources); + assert.isArray('takerTokenAmounts', takerTokenAmounts); + const functionSignature = + 'queryBatchOrdersAndSampleSells((address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bytes,bytes,bytes,bytes)[][],bytes[][],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); + return abiEncoder.strictDecodeReturnValue< + Array<{ orderFillableAssetAmounts: BigNumber[]; tokenAmountsBySource: BigNumber[][] }> + >(rawCallResult); + }, + getABIEncodedTransactionData(): string { + return self._strictEncodeArguments(functionSignature, [ + orders, + orderSignatures, + sources, + takerTokenAmounts, + ]); + }, + }; + } /** * Query native orders and sample buy quotes on multiple DEXes at once. * @param orders Native orders to query. diff --git a/packages/orderbook/CHANGELOG.json b/packages/orderbook/CHANGELOG.json index e3302a5b1b..7688b4a0b6 100644 --- a/packages/orderbook/CHANGELOG.json +++ b/packages/orderbook/CHANGELOG.json @@ -1,4 +1,13 @@ [ + { + "version": "2.1.0", + "changes": [ + { + "note": "Added `getBatchOrdersAsync` for fetching batches of orders", + "pr": 2427 + } + ] + }, { "timestamp": 1578272714, "version": "2.0.1", diff --git a/packages/orderbook/src/order_store.ts b/packages/orderbook/src/order_store.ts index faf1488645..f3c4f59e6a 100644 --- a/packages/orderbook/src/order_store.ts +++ b/packages/orderbook/src/order_store.ts @@ -25,6 +25,19 @@ export class OrderStore { } return orderSet; } + public async getBatchOrderSetsForAssetsAsync( + makerAssetDatas: string[], + takerAssetDatas: string[], + ): Promise { + const orderSets: OrderSet[] = []; + for (const makerAssetData of makerAssetDatas) { + for (const takerAssetData of takerAssetDatas) { + const orderSet = await this.getOrderSetForAssetsAsync(makerAssetData, takerAssetData); + orderSets.push(orderSet); + } + } + return orderSets; + } public async updateAsync(addedRemoved: AddedRemovedOrders): Promise { const { added, removed, assetPairKey } = addedRemoved; const orders = await this.getOrderSetForAssetPairAsync(assetPairKey); diff --git a/packages/orderbook/src/orderbook.ts b/packages/orderbook/src/orderbook.ts index e0fe97f16f..5031e6c6db 100644 --- a/packages/orderbook/src/orderbook.ts +++ b/packages/orderbook/src/orderbook.ts @@ -84,6 +84,26 @@ export class Orderbook { o => o.order.makerAssetData === makerAssetData && o.order.takerAssetData === takerAssetData, ); } + public async getBatchOrdersAsync(makerAssetDatas: string[], takerAssetDatas: string[]): Promise { + for (const [mi, makerAssetData] of makerAssetDatas.entries()) { + for (const [ti, takerAssetData] of makerAssetDatas.entries()) { + assert.isString(`makerAssetDatas[${mi}]`, makerAssetData); + assert.isString(`takerAssetDatas[${ti}]`, takerAssetData); + const assetPairKey = OrderStore.getKeyForAssetPair(makerAssetData, takerAssetData); + if (!(await this._orderStore.hasAsync(assetPairKey))) { + await this._orderProvider.createSubscriptionForAssetPairAsync(makerAssetData, takerAssetData); + } + } + } + const orderSets = await this._orderStore.getBatchOrderSetsForAssetsAsync(makerAssetDatas, takerAssetDatas); + return orderSets.map(orderSet => + Array.from(orderSet.values()).filter( + o => + makerAssetDatas.includes(o.order.makerAssetData) && + takerAssetDatas.includes(o.order.takerAssetData), + ), + ); + } /** * Returns all of the Available Asset Pairs for the provided Order Provider. */ diff --git a/python-packages/contract_wrappers/setup.py b/python-packages/contract_wrappers/setup.py index 82ed7b2936..08a6638d7d 100755 --- a/python-packages/contract_wrappers/setup.py +++ b/python-packages/contract_wrappers/setup.py @@ -117,17 +117,11 @@ class CleanCommandExtension(clean): ) ): try: - remove( - path.join( - "src", - "zero_ex", - "contract_wrappers", - contract, - "__init__.py", - ) - ) + print(f"Removing {contract}...", end="") + remove(contract) + print("done") except FileNotFoundError: - pass + print("file not found") class TestPublishCommand(distutils.command.build_py.build_py):